JVM GC调优本质是在吞吐量、延迟、内存占用三者间依业务场景取舍:批处理优先吞吐量,选Parallel GC并调-XX:GCTimeRatio;实时服务优先低延迟,选G1/ZGC并设-XX:MaxGCPauseMillis;资源受限则重内存效率,合理控堆与新生代比例。

面试中问到垃圾收集器(GC)参数调优,本质是考察你是否真正理解 JVM 内存模型、GC 工作机制,以及能否结合业务场景做合理取舍。不是背参数,而是讲清楚“为什么这么设”。
明确目标:吞吐量、延迟、内存占用,三者不可兼得
调优前必须先定义优先级:
- 批处理任务(如报表导出)——优先吞吐量,选 Parallel GC,调大 -XX:MaxGCPauseMillis(实际不生效,但可作为 Parallel 的目标参考),重点调 -XX:GCTimeRatio(默认99,即允许1%时间用于GC)
- 实时接口服务(如支付下单)——优先低延迟,选 G1 或 ZGC,关键参数是 -XX:MaxGCPauseMillis(G1 中建议设 20~200ms,ZGC 中设 10ms 也基本能达成)
- 资源受限环境(如容器小内存)——优先内存效率,避免 Full GC,用 -XX:+UseSerialGC 或 G1 配合 -XX:G1HeapRegionSize 控制分区粒度
G1 调优的三个落地抓手
G1 最常被问,但很多人只记 -XX:+UseG1GC,忽略实际调节逻辑:
- 初始堆与预期停顿绑定:G1 停顿时间受堆大小和存活对象影响,-Xms 和 -Xmx 设为相同值(避免扩容触发 Mixed GC),且总堆不宜超过 64GB(否则 Region 数过多,卡顿风险上升)
- 混合回收节奏可控:通过 -XX:G1MixedGCCountTarget=8(默认8)控制每次 Mixed GC 回收多少老年代 Region;配合 -XX:G1OldCSetRegionThresholdPercent=20(默认10)限制单次加入老年代回收集的 Region 比例
- 避免并发模式失败(CMF):出现 CMF 说明并发标记跟不上分配速度,需提前触发标记 —— 调小 -XX:G1ConcRefinementThreads(增加脏卡扫描线程),或增大 -XX:G1ReservePercent(默认10%,预留空间防晋升失败)
ZGC / Shenandoah 的关键配置不是“开箱即用”
它们主打低延迟,但需注意运行前提和边界:
- ZGC 要求 JDK 11+(生产推荐 JDK 17+),启用必须配 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC;堆大小建议 ≥ 8GB(小于 4GB 反而不如 G1);-XX:ZCollectionInterval 可强制周期性 GC,但一般不建议设,依赖自动触发
- Shenandoah 在 JDK 12+ 默认可用,需 -XX:+UseShenandoahGC;它对 CPU 更敏感,务必配 -XX:ShenandoahUncommitDelay=1000(毫秒)防止频繁内存归还影响性能
- 两者都不支持 CMS 的 -XX:CMSInitiatingOccupancyFraction,也不用调新生代比例(ZGC/Shenandoah 是全堆并发回收)
验证比设置更重要:用真实指标说话
调参后必须观测,不能只看 GC 日志是否“没报错”:
- 用 -Xlog:gc*:file=gc.log:time,tags,level(JDK 11+)代替旧版 -XX:+PrintGCDetails,日志更结构化
- 关注三项硬指标:GC 吞吐率 = (应用运行时间 / 总时间) × 100%、平均 GC 停顿(STW 时间)、晋升失败/Full GC 次数
- 压测时对比不同参数组合下 P99 响应时间波动 —— 如果 -XX:MaxGCPauseMillis 设为 50ms,但 P99 波动从 ±10ms 变成 ±80ms,说明该参数反而引发更多短频 GC,需回调

















