JVM18_CMS低延迟垃圾收集器、概述、原理、优缺点、参数设置、三色标记、ASTB 和 Incremental Update、记忆集与卡表(二)

⑤. CMS三色标记概述、问题、解决方案


①. 在并发标记的过程中,因为标记期间应用线程还在继续跑,对象间的引用可能发生变化,多标和漏标的情况就有可能发生。这里我们引入“三色标记”来给大家解释下,把Gcroots可达性分析遍历对象过程中遇到的对象, 按照“是否访问过”这个条件标记成以下三种颜色:


黑色(black):节点被遍历完成,而且子节点都遍历完成


灰色(gray): 当前正在遍历的节点,而且子节点还没有遍历


白色(white):还没有遍历到的节点,即灰色节点的子节点


JVM18_CMS低延迟垃圾收集器、概述、原理、优缺点、参数设置、三色标记、ASTB 和 Incremental Update、记忆集与卡表(二)


②. 根据三色扫描算法,如果有下面两种情况发生,则会出现漏扫描的场景:


把一个白对象的引用存到黑对象的字段里,如果这个情况发生,因为标记为黑色的对象认为是扫描完成的,不会再对他进行扫描。只能通过灰色的对象(CMS垃圾收集器)


(如上图中的D如果是白色对象没有引用,某一个时刻由于用户线程的影响,将A黑色对象引用了D的情况,解决办法:使用写屏障和增量更新解决)


某个白对象失去了所有能从灰对象到达它的引用路径(直接或间接)(G1垃圾收集器)


(如上图中的B灰色对象某一个时刻由于用户线程的影响将B到D的引用置为null,解决办法:使用写屏障和原始快照)


JVM18_CMS低延迟垃圾收集器、概述、原理、优缺点、参数设置、三色标记、ASTB 和 Incremental Update、记忆集与卡表(二)


③. 三色过程:如下图所示,假如说A引入了B,B引用了C,D没有被任何引用。那么首先我们的CMS首先扫描到了A,发现A有引用B,那么我们的CMS会将A标记为黑色,B标记为灰色,然后这时候,通过B又找到了C那么这个时候发现C已经没有任何引用了就会将C标记为黑色。但是我们的D到目前为止没有被任何引用,记住我这里说的条件!那么D从始至终都没有被扫描,此时就会一直是白色,对于白色的对象来说CMS在执行并发清理的时候就会将此类对象干掉。


但是这里有了一个问题:如果我们的扫描过程已经结束这一段了,但是此时此刻我的A突然引用了D类型怎么办,这样一来我们的D只要被GC干掉是不是就会出现问题?也就是说我这里产生了一个漏标的问题。当然,我们的JVM开发人员可不是*,这里他们用了一个操作叫做增量更新和写屏障来解决这种问题的。


JVM18_CMS低延迟垃圾收集器、概述、原理、优缺点、参数设置、三色标记、ASTB 和 Incremental Update、记忆集与卡表(二)



上一篇:JVM18_CMS低延迟垃圾收集器、概述、原理、优缺点、参数设置、三色标记、ASTB 和 Incremental Update、记忆集与卡表(三)


下一篇:JVM18_CMS低延迟垃圾收集器、概述、原理、优缺点、参数设置、三色标记、ASTB 和 Incremental Update、记忆集与卡表(一)