G1垃圾回收器

  1. 概念

G1(Garbage First)是服务端使用的垃圾回收器,用于多核、大内存的机器上,在大多数情况下可以实现指定的GC停顿时间,同时还保持较高的吞吐量。不同于之前的分代垃圾回收器,G1是逻辑上分代,物理上不分代。内存分为一个一个Region,有Eden区、Survivor区、Old区、还有Humongous区。

特点:并发回收;压缩空闲时间不会延长GC的暂停时间;更易预测的GC暂停时间;适用不需要很高的吞吐量的场景。

优点:追求吐吞量;追求响应时间:可以对STW进行控制;灵活: 分Region回收,优先回收花费时间少、垃圾比例高的Region。

  1. CSet和RSet

    CSet(Collection Set): G1一组可被回收的分区的集合;在CSet中存活的数据会在GC过程中被移动到另一个可用分区;CSet中的分区可以来自Eden空间、survivor空间或者老年代;CSet中的分区可以来自Eden空间、survivor空间或者老年代。

    RSet(RememberedSet):记录了其它Region中的对象到本region的引用;价值在于使得垃圾回收器不需要扫描整个堆就能找到谁引用了当前分区中的对象,只需要扫描RSet即可

了解:RSet与赋值的效率,由于RSet的存在,那么每次给对象赋值引用的时候,就得做一些额外的操作,指的是在RSet中做一下额外的记录(在GC中称为写屏障),这个写屏障不等于内存屏障。

  1. 新老年代的比例

    G1中新老年代的比例为5%-60%,一般不用手工指定,也不要手动指定,因为这是G1预测停顿时间的基准,G1去控制和预测STW就是通过动态调整这个比例来实现的。

  2. Region有多大?

    G1中Region不指定的时候,会根据实际的Heap大小来设定,取值范围为1 2 4 8 16 32M,设置参数为-XX:G1HeapRegionSize

  3. G1中的垃圾回收

    分YGC、FGC、Mixed GC类型。

    YGC: Eden空间不足触发,多线程并发执行。

    FGC:Old空间不足触发

    Mixed GC: 相当于CMS的回收过程,初始标记、并发标记、最终标记、筛选回收。触发Mixed GC的参数是-XX:InitiatingHeapOccupacyPercent, 默认为45%,当O区超过这个值启动MixedGC。

  4. G1是并行回收是否存在FGC?

    当分配对象非常快,回收不过来的情况下会产生FGC,jdk10以前是串行FullGC,之后是并行的FGC;

    如何避免FGC?

    降低MixedGC的触发一直,让MixedGC提早发生(默认是45%);扩内存;提高CPU性能(回收得快,业务逻辑产生对象的速度固定,垃圾回收越快,内存空间越大)。

三色标记法

  1. 三色的含义:

    白色指的是未被标记的对象,灰色指自身被标记,成员变量未被标记的对象,黑色指自身和成员变量都已标记完成的对象。

  1. 漏标

    CMS和G1在垃圾标记的过程中存在一个难点:在标记对象的过程中,对象的引用关系正在发生变化,会产生漏标的现象。漏标产生的充分必要条件:在remark过程中,黑色指向了白色,如果不对黑色重新扫描,则会漏标,会把白色D对象当做没有新引用指向从而回收掉;并发标记过程中,删除了所有从灰色到白色的引用,则会产生漏标,此时白色对象应该被回收,D漏标。

  1. 如何解决漏标

    CMS用的是Incremental Update算法, 增量更新,关注引用的增加,A->D,把黑色重新标记为灰色,下次重新扫描A的属性。

    G1用的是SATB(snapshot at the beginning),关注引用的删除,当B->D引用消失时,要把这个“引用”推到GC的堆栈,保证D还能被GC扫描到。

    为什么G1使用STAB? 当B->D引用消失时,会把这个引用推到GC的堆栈,下次扫描时候会拿到这个引用,由于有RSet的存在,不需要扫描整个堆去查找白色的引用,效率比较高。

  2. 总结

    CMS使用的并发标记算法是三色标记+Incremental Update

    CMS使用的并发标记算法是三色标记+SATB