SATB的标记问题解决之道与G1垃圾收集模式系统详解及最佳实践

继续接着上一次https://www.cnblogs.com/webor2006/p/11148282.html的理论学习,上一次学习到了这:

SATB的标记问题解决之道与G1垃圾收集模式系统详解及最佳实践_第1张图片

接着继续:

SATB详解:

  • 对于三色算法在concurrent的时候可能产生的漏标记问题,SATB在marking阶段中,对于从gray对象移除的目标引用对象标记为gray,对于black引用的新产生的对象标记为blcak;由于是在开始的时候进行snapshot,因而可能存在Floating Garbage。
  • 漏标与误标
    误标没什么关系,顶多造成浮动垃圾,在下次gc还是可以回收的,但是漏标的后果是致命的,把本应该存活的对象给回收了,从而影响的程序的正确性。
  • 漏标的情况只会发生在白色对象中,且满足以下任意一个条件。
    a、并发标记时,应用线程给一个黑色对象的引用类型字段赋值了该白色对象。
    b、并发标记时,应用线程删除所有灰色对象到该白色对象的引用。这是为何呢?举个例子来说明这种漏标现象的发生:
    SATB的标记问题解决之道与G1垃圾收集模式系统详解及最佳实践_第2张图片

    比如图上所示,有三个gray对象里面有个成员变量都指向了一个白色对象,此时这三个gray里面的成员变量还木有被扫描到,接着应用线程删除了所有灰色对象到该白色对象的引用,如下:
    SATB的标记问题解决之道与G1垃圾收集模式系统详解及最佳实践_第3张图片
    此时该white对象就成为了一个垃圾对象待回收了,目测现在这条件都是如预期,但是!!!假如在删除之前有一个黑色对象也引用该白色对象了,如下:

    SATB的标记问题解决之道与G1垃圾收集模式系统详解及最佳实践_第4张图片

    此时就会出现漏标的现象,本来该white对象不是垃圾反而当成垃圾被清理了。

  • 对于第一种情况,利用post-write barrier,记录所有新增的引用关系,然后根据这些引用关系为根重新扫描一遍。
  • 对于第二种情况,利用pre-write barrier,将所有既将被删除的引用关系的旧引用记录下来,最后以这些旧引用为根重新扫描一遍。

停顿预测模型:

  • G1收集器突出表现出来的一点是通过一个停顿预测模型根据用户配置的停顿时间来选择CSet的大小,从而达到用户期待的应用程序暂停时间。
  • 通过-XX:MaxGCPauseMillis参数来设置。这一点有点类似于ParallelScavenge收集器。关于停顿时间的设置并不是越短越好。 
  • 设置的时间越短意味着每次收集的CSet越小【设置的停顿时间越小则收集的垃圾越少,而收集的垃圾越少则意味着收集的region个数越少,而收集的region个数越少意味着由这些被收集的region所构成的CSet就越小】,导致垃圾逐步积累变多,最终不得不退化成Serial GC;停顿时间设置的过长,那么会导致每次都会产生长时间的停顿,影响了程序对外的响应时间。

G1的收集模式:

  • Young GC:收集年轻代里的Region。
  • Mixed GC:年轻代的所有Region + 全局并发标记阶段选出的收益高的Region。
  • 无论是Young GC还是Mixed GC都只是并发拷贝的阶段。
  • 分代G1模式下选择CSet有两种子模式,分别对应Young GC和Mixed GC:
    Young GC:CSet就是所有年轻代里面的Region
    Mixed GC:CSet是所有年轻代里的Region加上在全局并发标记阶段标记出来的收益高的Region。
  • G1的运行过程是这样的:会在Young GC和Mixed GC之间不断地切换运行,同时定期地做全局并发标记,在实在赶不上对象创建速度的情况下使用Full GC(Serial GC,也就是从G1会回收到备选的方案,一定要尽量避免此情况出现)
  • 初始标记是在Young GC上执行的,在进行全局并发标记的时候不会做Mixed GC,在做Mixed GC的时候也不会启动初始标记阶段。
  • 当Mixed GC赶不上对象产生的速度的时候就退化成Full GC,这一点是需要重点调优的地方。

G1最佳实践:

  • 不断调优暂停时间指标
    通过-XX:MaxGCPauseMillis=x可以设置启动应用程序暂停的时间,G1在运行的时候会根据这个参数选择CSet来满足响应时间的设置。一般情况下这个值设置到100ms或者200ms都是可以的(不同情况下会不一样),但是如果设置成50ms就不太合理。暂停时间设置的太短,就会导致出现G1跟不上垃圾产生的速度。最终退化成Full GC。所以对这个参数的调优是一个持续的过程,逐步调整到最佳状态。
  • 不要设置新生代和老年代的大小
    1、G1收集器在运行的时候会调整新生代和老年代的大小。通过改变代的大小来调整对象晋升的速度以及晋升年龄,从而达到我们为收集器设置的暂停时间目标。
    2、设置了新生代大小相当于放弃了G1为我们做的自动调优。我们需要做的只是设置整个堆内存的大小,剩下的交给G1自已去分配各个代的大小既可。
  • 关注Evacuation Failure
    Evacuation Failure类似于CMS里面的晋升失败,堆空间的垃圾太多导致无法完成Region之间的拷贝,于是不得不退化成Full GC来做一次全局范围内的垃圾收集。

你可能感兴趣的:(SATB的标记问题解决之道与G1垃圾收集模式系统详解及最佳实践)