cms通过并发标记与清除减少stw时间,核心是将长停顿拆为短停顿;需用写屏障处理漏标,重新标记阶段修正变动,但不压缩内存易碎片化;应调优触发阈值、配合parnew并监控并发失败。

CMS(Concurrent Mark-Sweep)垃圾收集器通过将大部分标记和清理工作与用户线程并发执行,显著减少 STW(Stop-The-World)时间,从而降低应用停顿。它的核心思路不是“避免暂停”,而是“把长暂停拆成多个短暂停”,尤其适合对响应时间敏感、堆内存中老年代对象存活率不高的场景。
并发标记阶段:边跑业务边扫描对象图
在初始标记(短暂 STW)后,CMS 启动并发标记线程,和应用线程一起运行。它从 GC Roots 出发,遍历整个老年代对象图,标记所有可达对象。这个过程不要求暂停应用,但存在“漏标”风险——即标记期间新创建或被引用的对象可能未被标记。为此 CMS 引入写屏障(Write Barrier),当程序修改引用(如 obj.field = newObj)时,把被修改的字段所在的卡页(Card)标记为“脏”,供后续重新标记阶段处理。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
重新标记阶段:修正并发期间的变动
这是一个短暂的 STW 阶段,主要做两件事:
• 扫描并处理并发标记期间产生的“脏卡”,确保所有新关联的对象都被标记;
• 处理在并发标记开始后、初始标记之前已进入老年代但尚未被扫描到的新生代晋升对象(通过扫描新生代中的老年代引用)。
该阶段耗时取决于脏卡数量和跨代引用规模,通常远短于完整标记。
并发清除阶段:边清理边继续服务
标记完成后,CMS 启动并发清除线程,直接回收所有未被标记的死对象空间。这个过程完全与用户线程并发,不触发 STW。注意:CMS 不压缩内存,因此会产生大量碎片。当碎片过多导致无法分配大对象时,会触发 Concurrent Mode Failure,被迫退化为 Serial Old 进行 Full GC(此时停顿明显拉长)。
关键调优点:防止并发失败,控制停顿节奏
要真正发挥 CMS 低停顿优势,需主动干预:
• 设置 -XX:CMSInitiatingOccupancyFraction 提前启动 CMS 周期(例如设为 70),避免老年代快满才触发,减少并发失败概率;
• 启用 -XX:+UseCMSInitiatingOccupancyOnly 禁用 JVM 自适应阈值,让触发时机更可控;
• 结合 ParNew(新生代并行收集器)使用,缩短新生代 GC 停顿,避免频繁晋升冲击老年代;
• 监控 concurrent mode failure 日志,一旦频繁出现,说明 CMS 已跟不上对象晋升速度,应考虑增大老年代、调低触发阈值,或迁移到 G1/ZGC。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










