我们知道JVM是利用可达性分析算法来判断对象是否存活,可达性分析算法理论上要求全过程基于一个能保障一致性的快照中进行分析,这意味着必须冻结用户线程的运行。
又由于GC Roots相比这个堆中的全部对象毕竟还是少数,且在各种优化中,他带来的停顿是非常短暂的,但是从GC Roots再继续往下扫描遍历对象图,这一步骤的停顿时间和堆的容量是成正比的,因此他会随着堆的变大而产生的停顿时间更长,会影响几乎所有的垃圾收集器,因此我们要是能够消减这部分的停顿,那收益就是系统级别的。
此时如果我们想要解决或者降低用户线程的停顿,就必须知道为什么必须要保障一致性快照上才能进行对象图的遍历,因此我们引入三色标记来作为辅助来理解
我们看到上面图片,当我们进行可达性分析的时候,当扫描到2节点的时候,这个时候,由于用户线程的的干扰,就会变成下面图片
这里2正准备到扫描4节点的时候,用户线程对应用进行了修改,把3到4的引用删除了,添加了2到4的引用,又由于2是黑色节点已经被扫描过了,就不会重新扫描他的子节点,此时4节点还是白的,因此JVM此时就会认为4已经不可达了,就会回收这个本应该存活的对象,就会导致2对象引用4的时候报错,这个中操作非常致命的.
为什么会出现这样的问题呢,原因如下
上面两者共存才会导致致命的问题,单单一个条件是没有影响的,如下图,删除一个旧的引用,就不会影响
或者添加一个引用也不会影响
因此只有两个条件同时存在,才会出现问题,所以我们只要破坏掉其中一条就可以了,因此出现了两种方案.
我们知道cms垃圾收集器使用的就是增量更新来做并发标记的,而G1则是利用原始快照来实现的,下次我们在再分析这两个垃圾收集器,敬请期待。