java垃圾回收之实现串行GC算法
我们可以选择JVM内置的各种算法。如果不通过参数明确指定垃圾收集算法, 则会使用宿主平台的默认实现。本章会详细介绍各种算法的实现原理。
下面是关于Java 8中各种组合的垃圾收集器概要列表,对于之前的Java版本来说,可用组合会有一些不同:
Young | Tenured | JVM options |
---|---|---|
Incremental(增量GC) | Incremental | -Xincgc |
Serial | Serial | -XX:+UseSerialGC |
Parallel Scavenge | Serial | -XX:+UseParallelGC -XX:-UseParallelOldGC |
Parallel New | Serial | N/A |
Serial | Parallel Old | N/A |
Parallel Scavenge | Parallel Old | -XX:+UseParallelGC -XX:+UseParallelOldGC |
Parallel New | Parallel Old | N/A |
Serial | CMS | -XX:-UseParNewGC -XX:+UseConcMarkSweepGC |
Parallel Scavenge | CMS | N/A |
Parallel New | CMS | -XX:+UseParNewGC -XX:+UseConcMarkSweepGC |
G1 | -XX:+UseG1GC |
- 年轻代和老年代的串行GC(Serial GC)
- 年轻代和老年代的并行GC(Parallel GC)
- 年轻代的并行GC(Parallel New) + 老年代的CMS(Concurrent Mark and Sweep)
- G1, 负责回收年轻代和老年代
因此这种GC算法不能充分利用多核CPU。不管有多少CPU内核, JVM 在垃圾收集时都只能使用单个核心。
要启用此款收集器, 只需要指定一个JVM启动参数即可,同时对年轻代和老年代生效:
java -XX:+UseSerialGC com.mypackages.MyExecutableClass
该选项只适合几百MB堆内存的JVM,而且是单核CPU时比较有用。 对于服务器端来说, 因为一般是多个CPU内核, 并不推荐使用, 除非确实需要限制JVM所使用的资源。大多数服务器端应用部署在多核平台上, 选择 Serial GC 就表示人为的限制系统资源的使用。 导致的就是资源闲置, 多的CPU资源也不能用来降低延迟,也不能用来增加吞吐量。
下面让我们看看Serial GC的垃圾收集日志, 并从中提取什么有用的信息。为了打开GC日志记录, 我们使用下面的JVM启动参数:
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps
产生的GC日志输出类似这样(为了排版,已手工折行):
****-05-26T14:45:37.987-0200: 151.126: [GC (Allocation Failure) 151.126: [DefNew: 629119K->69888K(629120K), 0.0584157 secs] 1619346K->1273247K(2027264K), 0.0585007 secs][Times: user=0.06 sys=0.00, real=0.06 secs]****-05-26T14:45:59.690-0200: 172.829: [GC (Allocation Failure) 172.829: [DefNew: 629120K->629120K(629120K), 0.0000372 secs]172.829: [Tenured: 1203359K->755802K(1398144K), 0.1855567 secs] 1832479K->755802K(2027264K), [Metaspace: 6741K->6741K(1056768K)], 0.1856954 secs] [Times: user=0.18 sys=0.00, real=0.18 secs]
此GC日志片段展示了在JVM中发生的很多事情。 实际上,在这段日志中产生了两个GC事件, 其中一次清理的是年轻代,另一次清理的是整个堆内存。让我们先来分析前一次GC,其在年轻代中产生。
Minor GC(小型GC)
以下代码片段展示了清理年轻代内存的GC事件:
****-05-26T14:45:37.987-02001 : 151.12622 : [ GC3 (Allocation Failure4 151.126:[DefNew5 : 629119K->69888K6 (629120K)7 , 0.0584157 secs] 1619346K->1273247K8(2027264K)9, 0.0585007 secs10] [Times: user=0.06 sys=0.00, real=0.06 secs]11
****-05-26T14:45:37.987-0200
– GC事件开始的时间. 其中-0200
表示西二时区,而中国所在的东8区为 +0800
。151.126
– GC事件开始时,相对于JVM启动时的间隔时间,单位是秒。GC
– 用来区分 Minor GC 还是 Full GC 的标志。GC
表明这是一次小型GC(Minor GC)Allocation Failure
– 触发 GC 的原因。本次GC事件, 是由于年轻代中没有空间来存放新的数据结构引起的。DefNew
– 垃圾收集器的名称。这个神秘的名字表示的是在年轻代中使用的: 单线程, 标记-复制(mark-copy), 全线暂停(STW) 垃圾收集器。629119K->69888K
– 在垃圾收集之前和之后年轻代的使用量。(629120K)
– 年轻代总的空间大小。1619346K->1273247K
– 在垃圾收集之前和之后整个堆内存的使用情况。(2027264K)
– 可用堆的总空间大小。0.0585007 secs
– GC事件持续的时间,以秒为单位。[Times: user=0.06 sys=0.00, real=0.06 secs]
– GC事件的持续时间, 通过三个部分来衡量:- user – 在此次垃圾回收过程中, 所有 GC线程所消耗的CPU时间之和。
- sys – GC过程中中操作系统调用和系统等待事件所消耗的时间。
- real – 应用程序暂停的时间。因为串行垃圾收集器(Serial Garbage Collector)只使用单线程, 因此 real time 等于 user 和 system 时间的总和。
更重要的信息蕴含在下一批数字中, 垃圾收集之后, 年轻代的使用量减少了 559,231K, 但堆内存的总体使用量只下降了 346,099K。 从中可以算出,有 213,132K 的对象从年轻代提升到了老年代。
此次GC事件也可以用下面的示意图来说明, 显示的是GC开始之前, 以及刚刚结束之后, 这两个时间点内存使用情况的快照:
文章图片
Full GC(完全GC)
理解第一次 minor GC 事件后,让我们看看日志中的第二次GC事件:
文章图片
文章图片
- user – 在此次垃圾回收过程中, 所有 GC线程所消耗的CPU时间之和。
- sys – GC过程中中操作系统调用和系统等待事件所消耗的时间。
- real – 应用程序暂停的时间。因为串行垃圾收集器(Serial Garbage Collector)只使用单线程, 因此 real time 等于 user 和 system 时间的总和。
文章图片
以上就是垃圾回收之实现串行GC算法的详细内容,更多关于串行GC算法的资料请关注脚本之家其它相关文章!
【java垃圾回收之实现串行GC算法】原文链接:https://plumbr.io/handbook/garbage-collection-algorithms-implementations#parallel-gc
推荐阅读
- Java|Java ArrayList实现班级信息管理系统
- Java基础之类与对象
- springboot项目java自动打包部署到服务器上思路
- Java常用实现八种排序算法与代码实现
- java|java 方法与数组基础使用详解
- 解析JavaSe的抽象类和接口
- Java|Java 继承与多态超详细梳理
- 短信平台API接口demo示例-JAVA/Message/MultiXSend
- 短信平台API接口demo示例-JAVA/Message/MultiSend
- Java数据结构最清晰图解二叉树前|Java数据结构最清晰图解二叉树前 中 后序遍历