CMS重标记阶段存量变量变动解析方案

作者:技术拾光

时间:2026-05-10

浏览:514

CMS重标记阶段的核心任务是修正并发标记期间因用户线程运行而产生的引用关系变更,防止漏标导致存活对象被错误回收。它通过写屏障和增量更新策略,在暂停用户线程后集中处理被修改的引用,并补全跨代引用。该阶段存在不可避免的停顿,优化关键在于减少并发标记期间的引用变动。

文章目录

CMS垃圾收集器重标记阶段的核心作用

谈及CMS垃圾收集器的重标记阶段,许多开发者会理解为“处理存量变量变动”。这一表述并不完全精确。该阶段的核心任务,是修正并发标记期间因用户线程持续运行而导致的引用关系变更,从而防止“漏标”问题,避免存活对象被错误回收。可以将其视作并发标记结束后的一次关键性“补考”与最终确认。

CMS重标记阶段存量变量变动解析方案

简而言之,重标记阶段的核心并非处理“存量变量变动”,而是修正并发标记过程中因用户线程持续运行而产生的引用关系变更,防止因漏标导致对象被错误回收。

为何必须设置重标记阶段?

这需要从并发标记的特性说起。在并发标记阶段,GC线程与用户线程是同时运行的。这就好比一边在清点仓库库存(标记存活对象),一边仍有货物在频繁进出(用户线程修改对象引用)。在此过程中,难免出现“账目不符”的情况,主要分为两类:

  • 已标记对象发生“黑→白”引用:一个已被标记为黑色(假定其所有引用均已扫描完毕)的对象,其字段被用户线程修改,指向了一个白色对象(尚未被访问)。这直接破坏了三色标记算法的基本约束,是导致“漏标”的主要原因。
  • 新生代晋升带来的新引用:在并发标记期间,若发生Young GC,部分存活对象会晋升至老年代。这些“新晋”对象及其引用关系,之前的并发标记过程并未覆盖。
  • 老年代内部的引用更新:例如向老年代的集合中添加元素、为Map赋值、修改数组内容等操作,都会新增对(可能仍是白色的)对象的引用。

重标记阶段如何“查漏补缺”?

CMS主要依靠写屏障与增量更新策略来应对。这套机制在并发标记期间“记录变更”,然后在重标记阶段集中处理。

  • 写屏障拦截与“变灰”:当用户线程执行类似 obj.field = newObj 的字段赋值操作时,写屏障会介入。若发现赋值者(obj)已是黑色,而被赋值者(newObj)仍是白色,它便会将这个黑色对象重新标记为灰色,并将其放入一个待扫描队列。
  • 集中扫描“灰色”对象:在随后的重标记阶段(此时用户线程暂停,即STW),GC线程会并发地扫描这些被“变灰”的对象,以及它们引用链上的所有对象,确保该链上的存活对象最终都被正确标记为黑色。
  • 补全跨代引用:同时,重标记阶段还会专门扫描新生代中仍然存活的对象,特别是那些持有指向老年代引用的对象,以补全因Young GC和对象晋升而产生的跨代引用遗漏。

该方案的局限性与代价

尽管增量更新策略大幅降低了漏标风险,但它并非万能,且存在成本:

  • 覆盖并非100%:写屏障本身存在性能开销,JVM会进行一些裁剪优化。某些非常规的引用操作,例如通过反射、JNI或特定Unsafe API进行的内存修改,可能会绕过写屏障的检测。
  • 策略的固有盲区:增量更新主要关注“黑→白”这类最危险的引用变化。对于“灰→白”或“白→白”等其他模式的变动,其处理逻辑可能不同或存在遗漏。
  • 不可避免的STW停顿:重标记阶段必须暂停所有用户线程。此停顿时间的长短,直接取决于有多少对象被“变灰”以及跨代引用的复杂程度。若并发标记阶段系统负载高、对象引用变更频繁,重标记的耗时可能会显著增加。

实际调优应关注哪些方面?

优化重标记阶段的核心思路,是减少并发标记期间引用关系的不确定性,从而降低重标记阶段的工作量与停顿时间:

  • 控制老年代对象的“活跃度”:尽量避免在老年代的大对象(如大型缓存、集合)中进行高频的引用更新操作。可考虑将频繁变动的数据移至堆外或使用更合适的数据结构。
  • 合理触发CMS:通过 -XX:CMSInitiatingOccupancyFraction 参数合理设置CMS启动的老年代占用阈值。启动过晚会导致并发标记时老年代空间所剩无几,对象移动和引用更新将更密集,增加变动风险。
  • 利用Young GC清扫:启用 -XX:+CMSScavengeBeforeRemark 参数,让重标记开始前先执行一次Young GC。此举可清理掉大部分已死亡的年轻代对象,大幅减少需要扫描的跨代引用数量,是降低重标记停顿的有效手段。
  • 监控是关键:密切关注GC日志中 [GC (CMS Remark) 这一行的持续时间。若此时间呈现明显增长趋势,即是一个明确信号,表明并发标记期间对象引用变动过大,需结合具体业务代码进行排查。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章