gc性能优化需聚焦吞吐量、停顿时间、回收频率三大硬指标:吞吐量=用户代码时间÷总时间,要求≥95%;停顿时间看p95/p99真实stw时长;回收频率通过jstat的ygc/fgc次数评估;三者相互制约,调优须同步监控联动变化。

GC 性能不是靠感觉判断的,得用具体数字说话。核心就三个可量化的硬指标:吞吐量、停顿时间、回收频率。它们彼此制约,调优本质是在三者之间按业务需求做取舍。
吞吐量:算清“干活时间占比”
公式很直接:用户代码执行时间 ÷(用户代码执行时间 + GC 时间)。比如程序运行 100 秒,其中 GC 占了 2 秒,吞吐量就是 98%。生产环境通常要求不低于 95%,否则说明 GC 开销过大,正在蚕食业务能力。重点看 YGCT(年轻代 GC 总耗时)和 FGCT(Full GC 总耗时) 在 jstat 输出里的累计值,结合应用总运行时长就能算出实际吞吐量。
停顿时间:盯住单次 STW 的毫秒级波动
用户感知最直接的是卡顿,也就是每次 Stop-The-World 的持续时间。不能只看平均值,更要关注 P95、P99 停顿——比如 100 次 Minor GC 中,最长那次花了 120ms,就可能触发接口超时。用 -XX:+PrintGCDetails -XX:+PrintGCTimeStamps 开启 GC 日志后,每条日志里 “[Times: user=0.042 sys=0.005, real=0.047 secs]” 中的 real 就是真实停顿时间。CMS 和 G1 的目标就是把这类值压到几十毫秒内。
回收频率:统计单位时间内的 GC 次数
高频 GC 本身是预警信号。jstat 的 YGC 和 FGC 列直接给出次数,再结合采样间隔就能算出频率。例如 5 分钟内发生 300 次 Minor GC,意味着平均 1 秒一次,明显异常。背后通常是 Eden 区太小或对象存活率高;而 Full GC 频繁(比如每小时几次),大概率是老年代空间不足或内存泄漏。频率降不下来,光优化单次耗时意义有限。
三指标联动:别孤立调一个参数
想降低停顿时间,换 G1 或 ZGC 是直接手段,但可能略微拉低吞吐量;想提高吞吐量,用 Parallel GC 效果好,但单次停顿会变长;把堆内存设得过大能减少频率,却会让单次 Full GC 更久。所以调优必须同步监控三项指标变化:
- 增大 -Xmx 后,看 FGC 是否减少,但 real time 是否变长
- 调整 -XX:NewRatio 后,观察 YGC 频率和平均停顿是否此消彼长
- 切换 GC 器后,用 GC 日志对比吞吐量、最大停顿、总 GC 次数三组数字











