JVM G1垃圾收集器调优实战:从Full GC频发到稳定低延迟
JVM G1垃圾收集器调优实战:从Full GC频发到稳定低延迟
服务上线后每隔几小时出现一次长达数秒的停顿,接口毛刺明显,日志里满是 [Full GC (Allocation Failure)]——这是很多 Java 团队从 CMS 迁到 G1 后都会踩的坑。G1 的设计目标是可控停顿,但参数不当反而比 CMS 更不稳。本文以一次真实生产调优为例,梳理 G1 的关键参数与排查路径。
一、先看懂 G1 的日志
调优前先开 -Xlog:gc*,gc+humongous=debug(JDK11+)。重点看三类信息:Young GC 的耗时与 Eden 区变化、Mixed GC 的回收效率、以及 humongous allocation 的占比。大量 humongous 对象(超过 Region 一半大小的对象)是 G1 Full GC 的头号诱因,日志里 Humongous regions 持续增长就要警惕。
二、MaxGCPauseMillis 不要盲目调小
-XX:MaxGCPauseMillis=200 是最常被误用的参数。设得太小(如 50ms)会让 G1 把年轻代压得极小,Young GC 频率暴增,总吞吐反而下降。经验值:交互型服务 100~200ms,批处理任务直接放开。调参后观察 G1 Evacuation Pause 的实际均值是否贴近目标,而不是只看单次最大值。
三、Humongous 对象的两种治理
一是改代码:大 JSON 解析、大 List 拷贝尽量流式处理;调大 -XX:G1HeapRegionSize=16m 让大对象不再跨 Region。二是提前触发并发标记周期:-XX:InitiatingHeapOccupancyPercent 从默认 45 降到 35,让 Mixed GC 更早介入回收老年代,避免大对象堆积到扛不住。
四、Mixed GC 效率不足怎么办
如果 Mixed GC 回收后老年代占用仍降不下来,检查 G1MixedGCCountTarget(默认 8)与 G1HeapWastePercent(默认 5)。适当提高前者、降低后者,可以让更多老年代 Region 进入回收候选。配合 -XX:G1ReservePercent=15 预留空间,降低晋升失败(to-space exhausted)的概率。
五、大促前的终极兜底
实在无法杜绝 Full GC 时,加 -XX:+G1PeriodicGCInterval(JDK12+)在低峰期主动触发回收;堆预算充足的话直接扩大 -Xms=-Xmx 固定堆大小,避免动态伸缩带来的额外停顿。最后切记:所有参数逐个改、观察 24 小时再改下一个,一次全改等于没调。
总结:G1 调优的本质是「用吞吐换延迟的再平衡」。抓住 humongous 对象、暂停目标、Mixed GC 效率三条主线,绝大多数 Full GC 频发问题都能定位到根因。
- 点赞
- 收藏
- 关注作者
评论(0)