Appearance
CMS GC
CMS(Concurrent Mark Sweep)是面向低停顿的老年代回收器。它通过并发标记和并发清除减少应用停顿,但会带来 CPU 竞争、浮动垃圾和内存碎片问题。CMS 已属于老系统维护知识,新项目通常不再选择它。
定位
| 维度 | 说明 |
|---|---|
| 核心目标 | 降低老年代回收停顿 |
| 执行方式 | 初始标记和重新标记 STW,其余阶段并发 |
| 典型组合 | ParNew + CMS |
| 主要问题 | 内存碎片、浮动垃圾、并发失败 |
| 新项目建议 | 优先 G1、ZGC、Shenandoah |
工作阶段
text
初始标记(STW) -> 并发标记 -> 重新标记(STW) -> 并发清除 -> 重置初始标记
短暂停顿,标记 GC Roots 直接可达对象。
并发标记
GC 线程和应用线程一起运行,沿引用链继续标记对象。
重新标记
再次短暂停顿,修正并发期间应用线程修改引用造成的变化。
并发清除
回收不可达对象,但不做压缩整理,因此可能产生内存碎片。
常见问题
Concurrent Mode Failure
CMS 并发回收还没完成,老年代就无法继续分配,JVM 退回更重的 Full GC。
处理方向:
- 提前触发 CMS。
- 增大老年代空间。
- 降低对象晋升速度。
- 评估迁移到 G1。
内存碎片
CMS 使用标记-清除,不压缩对象。老年代总空闲空间够,但连续空间不够时,大对象仍可能分配失败。
处理方向:
- 减少大对象分配。
- 观察 Full GC 和压缩行为。
- 迁移到带整理或分区能力的回收器。
CPU 竞争
并发阶段 GC 线程和应用线程同时运行,可能抢 CPU。
排查:
bash
top -H -p <pid>
jstat -gcutil <pid> 1000老系统参数识别
老服务中可能看到:
bash
-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=70
-XX:+UseCMSInitiatingOccupancyOnly这些参数不适合直接迁移到新 JDK。升级时应先确认 JDK 支持情况,再设计 GC 迁移方案。
迁移建议
| 当前问题 | 迁移方向 |
|---|---|
| CMS 碎片导致 Full GC | G1 |
| 停顿仍无法满足 | ZGC / Shenandoah |
| 系统主要是吞吐型 | Parallel 或 G1 |
| JDK 版本较老 | 先拆分 JDK 升级和 GC 迁移风险 |
迁移前后对比:
- 吞吐量。
- P95/P99/P999 延迟。
- GC 总 CPU。
- Full GC 次数。
- 堆和 RSS。
