JVM并发标记漏标问题由应用线程修改引用导致三色标记滞后,CMS用增量更新(写屏障拦截黑→白新增引用并重标灰色)防御,G1用原始快照(SATB,写屏障记录灰→白删除前的旧引用)防御,二者不可混用。
JVM并发标记阶段的漏标问题,本质是应用线程修改引用关系时,三色标记状态跟不上变化——黑色对象直接指向白色对象,或灰色对象删掉对白色对象的引用,都会导致本该存活的对象被误判为垃圾。增量更新和原始快照不是可选技巧,而是CMS与G1各自选定的、必须启用的底层防御机制。
它假设最危险的操作是黑色对象突然新增对白色对象的引用——这会绕过标记流程,让白色对象彻底“隐身”。CMS用写屏障实时拦截这类赋值动作:
G1换了一种思路:不拦新增,而是抢在引用被覆盖或置 null 前,快照下那个即将消失的旧对象。它信任标记开始时的存活图,确保“曾经活过”的对象不会被跳过:
CMS面向低延迟,倾向精准控制,宁可多花点写入开销也要避免漏标;G1面向大堆与混合回收,优先压低写屏障频率,用可控的多标换取更稳的 STW 时间。实际配置中:
理解它们的关键,不是背定义,而是抓住动作触发点:一个抓“新增”,一个抓“删除”;一个拉回灰色,一个快照旧引用。机制不同,目标一致——守住那条不能越界的生死线。