1.确认问题
通过GC日志和监控工具来观察对应GC的一个频率,停顿时间,堆内存使用率这些指标;
定位是频繁的Minor GC还是Full GC, 还是单次停顿时间过长了
1 | G1 停顿目标示例 |
2.调堆的大小
这是最直接的手段,年轻代太小会导致频繁的Minor GC,年老代太大会导致频繁的Full GC;
一般堆大小设置为存活对象大小的3到4倍,年轻代占堆的1/3 或1/2;
3.选GC算法
对延迟敏感的场景,G1或ZGC;对吞吐量敏感的场景,一般选择Parallel GC;
在线查看GC日志
1 | 查看进程 PID |
如果是GC的.log日志,一般会用jstat来查看
如果是GC的.jfr日志,一般会用Java Mission Control来查看
那如果突然OOM,怎么看对应时间点的GC日志呢?
1 | 动态堆 dump |
总结
如果线上突发 OOM,而之前没有配置 GC 日志或 HeapDump,我会先确认 JVM 是否仍然存活;
如果进程还活着,我会用 jcmdGC.heap_dump 在线抓取堆 dump,结合 jstat -gc 查看 Minor / Full GC 次数、堆占用情况,分析老年代压力和对象晋升趋势;
如果进程已经崩掉,我会检查操作系统级 core dump 或 crash log,结合 jhsdb 分析对象分布;
即使事前没有日志,也可以事后定位 OOM 根因,并制定堆内存、对象创建或泄漏优化方案