cms调优核心是平衡低停顿与稳定性,需避免并发模式失败、remark过长和内存碎片,必须结合业务特征动态调整,并通过gc日志验证效果。

CMS垃圾回收器的参数调优核心在于平衡低停顿与稳定性,避免并发模式失败、Remark阶段过长和内存碎片堆积这三类高频问题。它不是“开箱即用”的方案,必须结合业务对象生命周期、晋升速率和老年代占用趋势来动态调整。
基础启用与配套设置
CMS仅负责老年代回收,必须搭配ParNew作为新生代收集器。JDK8+需显式启用,缺一不可:
- -XX:+UseConcMarkSweepGC:启用CMS老年代回收
- -XX:+UseParNewGC:启用并行新生代回收(CMS默认要求)
- -Xmn 或 -XX:NewSize/-XX:MaxNewSize:必须手动指定新生代大小;NewRatio在CMS下常被忽略,不建议依赖
- 堆总大小建议控制在6G以内,超大堆会显著拉长Full GC(退化为Serial Old)的STW时间
关键触发与阈值控制
CMS是否及时启动,直接决定是否发生Concurrent Mode Failure(并发模式失败),这是最危险的异常之一:
- -XX:CMSInitiatingOccupancyFraction=70:设为70(即老年代使用率达70%时触发CMS周期),比默认92更保守,预留空间应对浮动垃圾
- -XX:+UseCMSInitiatingOccupancyOnly:强制始终按上述阈值触发,禁用JVM自适应调整,保障行为可预测
- 配合监控看老年代晋升速率,若每分钟晋升超50MB,70%阈值可能仍偏高,需进一步下调至60–65
缩短STW阶段耗时
初始标记(Initial Mark)和重新标记(Remark)是仅有的两次STW,其中Remark最易成为瓶颈:
- -XX:+CMSScavengeBeforeRemark:Remark前强制执行一次Minor GC,大幅减少需扫描的跨代引用对象
- -XX:+CMSParallelRemarkEnabled:启用多线程Remark,降低单核压力
- -XX:+CMSParallelInitialMarkEnabled:同理加速Initial Mark(对大堆效果明显)
- 若Remark仍超200ms,检查是否存在大量长期存活但频繁修改引用关系的对象(如缓存容器、监听器列表)
应对碎片与退化风险
CMS用标记-清除算法,不移动对象,碎片随运行时间累积,最终导致Promotion Failed或无法分配大对象:
- -XX:+UseCMSCompactAtFullCollection:每次Full GC后执行内存压缩(代价是延长该次FGC时间)
- -XX:CMSFullGCsBeforeCompaction=1:每1次Full GC后整理一次,比每次更均衡
- 生产环境建议预留30%–40%老年代空间作“浮动垃圾缓冲”,避免因碎片+新分配同时发生而触发退化
- 长期运行服务可考虑定期滚动重启,比强压碎片更可控;JDK8+项目建议评估迁移到G1,原生支持压缩与可预测停顿
不复杂但容易忽略:所有调优必须基于真实GC日志验证,推荐用jstat -gc -h10 pid 1000持续采样,重点关注FGC次数、CMS GC周期耗时、老年代使用率曲线及Remark STW时间。参数改完不看日志,等于没调。











