1.GC分类与性能指标
1.1 垃圾回收器概述
垃圾回收器没有在规范中进行过多的规定,可以由不同的厂商、不同版本的JVM来实现由于JDK的版本处于高速迭代过程中,因此Java发展至今已经衍生了众多的GC版本从不同角度分析垃圾收集器,可以将GC分为不同的类型
1.2 垃圾回收器分类
1.2.1 按线程数分,可以分为串行垃圾回收器和并行垃圾回收器
1.2.2 按工作模式分,可以分为并发式垃圾回收器和独占式垃圾回收器
1.2.3 按碎片处理方式分,可分为压缩式垃圾回收器和非压缩式垃圾回收器
压缩式垃圾回收器会在回收完成后,对存活对象进行压缩整理,消除回收后的碎片
再分配对象空间使用:指针碰撞 非压缩式的垃圾回收器不进行这步操作
再分配对象空间使用:空闲列表
1.2.4 按工作的内存区间分,可分为年轻代垃圾回收器和老年代垃圾回收器
1.3 评估GC的性能指标
吞吐量:运行用户代码的时间占总运行时间的比例
总运行时间:程序的运行时间+内存回收的时间 垃圾收集开销:吞吐量的补数,垃圾收集所用时间与总运行时间的比例暂停时间:执行垃圾收集时,程序的工作线程被暂停的时间收集频率:相对于应用程序的执行,收集操作发生的频率内存占用:Java堆区所占的内存大小快速:一个对象从诞生到被回收所经历的时间
上述标黄的三项是主要的性能指标,这三者共同构成一个“不可能三角”。三者总体的表现会随着技术进步而越来越好。一款优秀的收集器通常最多同时满足其中的两项
这三项中,暂停时间的重要性日益凸显。因为随着硬件发展,内存占用多些越来越能容忍,硬件性能的提升也有助于降低收集器运行时对应用程序的影响,即提高了吞吐量。而内存的扩大,对延迟反而带来负面效果。
简单来说,主要抓住2点:吞吐量,暂停时间。
1.3.1 吞吐量
1.3.2 暂停时间
1.3.3 吞吐量和暂停时间对比:
2.不同的垃圾回收器概述
2.1 垃圾回收器发展史
2.2 七款经典垃圾回收器
七种经典垃圾回收器和垃圾分代之间的关系
垃圾回收器的组合关系
如何查看默认回收器
-XX:+PrintCommandLineFlags:查看命令行相关参数(包含使用的垃圾回收器)使用命令行指令:jinfo -flag 相关垃圾回收器参数 进程ID
3.Serial回收器:串行回收
4.ParNew回收器:并行回收
5.Parallel回收器:吞吐量优先
6.CMS回收器:低延迟
注意:重新标记的是之前怀疑是垃圾的垃圾,如果在并发标记阶段新生成的垃圾(原来没有被怀疑是垃圾),重新标记是不会标记的 。
CMS收集器可以设置的参数
7.G1回收器:区域划分代式
7.1 既然有了前面几个强大的GC,为什么还要发布Garbage First GC?
7.2 为什么名字叫做Garbage First?
我的理解:G1看中的是回收效率,即使有个region快满了,然后去回收发现几乎无法回收,都是可达对象,不能产生空闲内存,这样就浪费了时间。
7.3 G1概述
7.4 G1优点:
7.5 G1缺点:
7.6 G1参数设置
最大GC暂停时间不能设置的太短,如果太短,G1回收器能够回收的region就会更少,就会导致很多region永远不会回收,最后内存占满执行Full GC。
7.7 G1常见操作步骤
7.8 G1的适用场景
7.9 Region:化整为零
7.10 G1垃圾回收过程:
主要包含以下三个环节:
年轻代GC(Young GC),对年轻代的回收,是回收年轻代所有的region,包括所有的eden区和survivor区的region老年代并发标记过程(Concurrent Marking)混合回收(Mixed GC)(如果需要,单线程、独占式、高强度的Full GC还是继续存在的。它针对GC的评估失败提供了一种失败保护机制,即强力回收。)
上述例子的每45秒重新分配2G内存是指每45秒进行一次全年轻代的YGC,每31小时进行mixed GC。
7.10.1 Remembered Set 记忆集
一个对象被不同区域引用的问题:
一个Region不可能是鼓励的,一个Region中的对象可能被其他任意Region中的对象引用。判断对象存活时,是不是要扫描整个堆区才能保证准确?在其他的分代收集器,也存在这样的问题(但是G1更突出)一个老年代的region的对象引用一个年轻代的region的对象,是不是进行YGC的时候同时也要扫描老年代?这样的话会降低YGC的效率。
解决方法: 我的理解:每次进行引用的时候,都会在region自己的Rset中记录下,是哪个region中的对象引用了当前region中的对象。每次对当前region进行回收时,在GC Roots中假如这个Rset,如果Rset中有引用就不能被回收。(注意,这里是我的简单理解,引用时并不是直接记录到Rset中,而是记录到Card中)
Write Barrier:写屏障 CardTable:卡表
7.10.2 回收过程一:年轻代GC
dirty card queue:
7.10.3 回收过程二:并发标记过程(针对老年代)
7.10.4 回收过程三:混合回收
回收过程四:Full GC
7.11 G1优化建议:
8.垃圾回收器总结:
8.1 怎么选择垃圾回收器?
9.GC日志分析
9.1 jdk8下PrintGC的日志:
9.2 jdk8下PrintGCDetails的日志:
9.3 补充说明
YGC: Full GC:
9.4 日志分析工具:
导出日志:
10.垃圾回收器的新发展
10.1 Open JDK12的Shenandoah GC:
12.2 ZGC