cms采用增量更新解决漏标,即在写屏障中拦截黑色对象新增对白色对象的引用,并将该黑色对象重标为灰色以重新扫描;g1则采用satb,在赋值前记录被覆盖的旧引用并标记为灰色,实现前置防御。

三色标记法在并发标记阶段确实会面临漏标风险,核心在于用户线程修改引用时,GC线程的标记状态已“固化”,导致本该存活的对象被误判为垃圾。漏标不是随机发生,它必须同时满足两个条件:一是灰色对象断开了对白色对象的引用;二是黑色对象在此期间建立了对该白色对象的新引用。一旦触发,该白色对象将永远留在白色集合中,最终被错误回收——这是JVM必须避免的严重问题。
漏标发生的典型场景
假设GC线程已将对象E标记为灰色(正在处理),而对象D已是黑色(标记完成)。此时用户线程执行两步操作:
① objE.fieldG = null(灰色E断开对白色G的引用);
② objD.fieldG = G(黑色D新增指向白色G的引用)。
由于D是黑色,GC不会再重新扫描它;而E已断开G,也不会再把G推入灰色队列。G就此“消失”在标记视野中,标记结束后仍为白色,被当作垃圾清除。
增量更新(Incremental Update):CMS的选择
该方案聚焦于“新增引用”这一动作,在写屏障中拦截所有黑色→白色的新引用,并立即将被引用的白色对象重新标记为灰色,加入待扫描队列。
• 本质是“补救式扫描”:不阻止引用变更,而是事后追加标记;
• 要求每次写操作都触发屏障逻辑,开销略高;
• CMS采用此策略,配合其以吞吐量优先的设计取向。
原始快照(SATB):G1与ZGC的核心机制
SATB在引用被修改前,先通过写屏障“拍下快照”——即记录下即将被覆盖的旧引用(如objD.fieldG原指向的旧对象),并将其标记为灰色,确保该对象不会因后续断开而漏标。
• 本质是“前置防御”:在删除发生前保留关联路径;
• 更适合G1的区域化管理与ZGC的低延迟目标,能大幅减少重扫量;
• 配合读屏障(如ZGC),还可支持更激进的并发操作。
为什么G1选SATB而CMS选增量更新?
• G1强调预测性停顿控制和区域独立回收,SATB产生的灰色对象可按Region分批处理,更契合其记忆集(Remembered Set)维护逻辑;
• CMS面向老年代并发清理,增量更新对已有并发标记流程侵入小,改造成本低;
• SATB天然抑制浮动垃圾增长,而增量更新可能引入更多重扫,影响CMS的吞吐目标。











