看懂gc日志关键数字比背参数更重要,需结合吞吐(用户线程占比)、延迟(单次stw时间)、容量(老年代占用率、碎片等)三类指标,在业务场景中综合判断系统稳定性与瓶颈根源。

看懂 GC 日志里的关键数字,比背参数更重要。真正影响系统稳定性的,往往不是选了哪个收集器,而是它在真实负载下是否“跟得上”——对象分配速率、GC 频次、停顿时间、内存碎片程度,这些数据会直接说话。
关注三类核心指标:吞吐、延迟、容量
性能评估不能只盯单个数字,要结合业务场景看组合表现:
- 吞吐量:用户线程运行时间占比(比如 95%)。适合批处理或后台任务,可接受稍长但不频繁的停顿;
- 延迟:单次 GC 最大暂停时间(如 STW ≤ 10ms)。对响应敏感的服务(API、实时计算)必须严控;
- 堆内存使用效率:老年代长期占用率是否持续攀升、是否频繁触发 Full GC、是否存在内存碎片(尤其 CMS/SerialOld 易见)。
从 GC 日志快速定位问题模式
一条典型 G1 日志:[GC pause (G1 Evacuation Pause) (young) 234M->86M(1024M), 0.0422310 secs],重点抓三个数:
- 234M→86M:回收前后的堆使用量,差值(148M)是本次清理的有效空间。若每次回收后仍逼近阈值,说明对象存活率高或分配过快;
- (1024M):当前堆总容量。若长期 >75% 使用,G1 会提前启动并发标记,增加 CPU 开销;
- 0.042s:实际 STW 时间。连续多次超过 50ms 要警惕,尤其是服务端接口 P99 延迟已接近 SLA 时。
对比不同收集器的典型信号
不是所有停顿都一样,要看谁在干活、干了什么:
-
G1:日志中频繁出现
to-space exhausted或evacuation failed,说明年轻代晋升压力大,需调大-XX:G1HeapRegionSize或降低-XX:MaxGCPauseMillis目标(别设太激进); -
ZGC/Shenandoah:停顿稳定在 10ms 内,但 GC 日志里
Pause Phases时间变长,可能因并发标记阶段扫描到大量跨代引用,检查是否对象图太深或软/弱引用滥用; -
Parallel GC:频繁
Full GC且耗时陡增,大概率是老年代碎片化或元空间泄漏(注意Metaspace区增长趋势)。
用工具验证,别只信日志
日志是线索,可视化才是证据:
- 用
jstat -gc <pid> 1s</pid>实时观察 Eden/Survivor/Old 区变化节奏,看是否“刚清完又爆满”; - 用
jcmd <pid> VM.native_memory summary</pid>查 Native Memory 是否持续上涨(ZGC/G1 的额外开销容易被忽略); - 配合 Prometheus + Grafana 把 GC 次数、平均停顿、内存各区域水位做成曲线,异常点一目了然——比如某次发布后 Young GC 频次翻倍,大概率是新代码引入了短生命周期对象暴增。
不复杂但容易忽略。真正有用的判断,来自把数字放进具体上下文里读——这次 GC 是救火,还是常态?是治标,还是暴露了设计瓶颈?










