平滑升级cms到g1需分三阶段:先启用-xx:+useg1gc并保留原堆配置,确保基础稳定;再按需设置maxgcpausemillis等参数启用g1特性;最后更新监控、告警及清理cms残留。

平滑升级从 CMS 到 G1,关键不是“一步切换”,而是分阶段验证、渐进调优。核心思路是:先让 G1 在 CMS 的运行习惯下稳定工作,再逐步启用 G1 的优势特性(如可预测停顿、混合回收),最后关闭 CMS 遗留配置并完成日志与监控对齐。
一、升级前必须确认的基础条件
避免踩坑的第一步是检查环境是否满足 G1 的基本要求:
- JDK 版本 ≥ 7u4(推荐 JDK 8u202+ 或 JDK 11+),确保 G1 功能完整且修复了早期稳定性问题
- 堆内存建议 ≥ 4GB;若堆小于 2GB,G1 反而可能因 Region 管理开销导致 Young GC 更频繁
- 停用所有 CMS 专用参数(如 -XX:+UseConcMarkSweepGC、-XX:CMSInitiatingOccupancyFraction),否则 JVM 启动会直接报错
- 确保应用不依赖 CMS 特有的行为,例如:未显式调用 System.gc() 触发 Concurrent Mode Failure 应对逻辑
二、第一阶段:G1 基础启用与等效运行
目标是让 G1 “先跑起来”,行为接近原有 CMS,不引入新风险:
- 添加基础参数:-XX:+UseG1GC,其余 GC 相关参数全部移除(包括新生代大小、老年代比例等)
- 保留原有堆大小(-Xms/-Xmx)和元空间配置,不急于调整
- 开启详细 GC 日志:-Xlog:gc*,gc+heap=debug,gc+ergo*=info:file=gc.log:tags,time,uptime,level(JDK 10+)或兼容旧版的 -XX:+PrintGCDetails -XX:+PrintGCTimeStamps
- 上线后重点观察:Young GC 频率是否明显升高?Mixed GC 是否迟迟不触发?有没有 Full GC 回归?这些信号说明 G1 还没适应当前对象晋升节奏
三、第二阶段:按需启用 G1 核心能力
确认基础运行稳定后(通常需 3–5 天生产流量验证),再打开 G1 的差异化功能:
- 设置目标停顿时间:-XX:MaxGCPauseMillis=200(建议初始值比原 CMS 实测 P99 停顿高 20%~30%,如原为 150ms,设为 200ms)
- 控制 Mixed GC 范围:-XX:G1MixedGCCountTarget=8(默认 8 次 Mixed GC 完成一轮并发标记周期,避免单次回收压力过大)
- 调节老年代回收积极性:-XX:G1HeapWastePercent=5(当堆中预估可浪费空间超 5%,才启动 Mixed GC,防止过早回收)
- 注意:不要同时调大 -XX:G1NewSizePercent 和 -XX:G1MaxNewSizePercent,G1 新生代是弹性伸缩的,人为锁死反而破坏自适应能力
四、第三阶段:收尾与长期运维适配
升级完成不等于结束,需同步更新配套机制:
- 替换监控指标:CMS 关注 “concurrent mode failure” 次数,G1 改为关注 “to-space exhausted” 和 “evacuation failure” 日志关键词
- 调整告警阈值:G1 的 Young GC 停顿通常更短但更频繁,应降低单次停顿告警线(如 ≤50ms),提高频率类告警(如 1 分钟内 >30 次)
- 清理残留代码:移除所有针对 CMS 的 JMX 检测逻辑(如监听 ConcurrentMarkSweep GC 名称)、以及基于 CMS 日志格式的日志解析脚本
- 定期检查 RSet 占用:jstat -gc
中 G1RSet 列若持续增长,说明跨 Region 引用过多,需检查大对象或长生命周期缓存设计











