java-gc
Java GC 频繁或停顿过长的定位
现象
接口延迟尖刺、吞吐下降,GC 日志显示频繁 Young/Full GC,STW 停顿变长;CPU 使用率升高但业务吞吐不增。
快速定位
jstat -gcutil <pid> 1000 10
jcmd <pid> GC.heap_info
jcmd <pid> GC.class_histogram | head -30
jcmd <pid> VM.flags
GC 日志(JDK 9+):
java -Xlog:gc*:file=gc.log:time,uptime,level,tags -jar app.jar
常见根因
- 堆太小,频繁 Young GC;堆太大,Full GC 停顿长。
- 分配速率过高,短命对象过多。
- 老年代对象增长快或存在泄漏。
- 大对象/ humongous 对象导致特殊 GC 行为。
- GC 收集器选择不适合当前延迟/吞吐目标。
- 容器 CPU limit 导致 GC 线程不足。
修复
- 先看 GC 日志的停顿时间、频率和回收效果。
- 降低分配速率,复用对象,避免大对象频繁创建。
- 根据延迟/吞吐目标选择 G1/ZGC/Shenandoah 等收集器。
- 调整堆大小和新生代比例,避免过小或过大。
- 排查老年代泄漏;用堆直方图/快照对比。
- 容器 CPU limit 要给 GC 线程留足资源。
- 建立 GC 停顿和频率监控,不要只看平均延迟。
相关命令
java — JVM/GC 参数
jstat / jcmd — GC 诊断
jmap — 堆直方图