一、常见 OOM 类型
| 错误 | 含义 | 常见原因 |
|---|---|---|
| Java heap space | 堆溢出 | 内存泄漏、堆太小、大对象 |
| Metaspace | 元空间溢出 | 动态生成类过多(如 CGLIB 代理) |
| StackOverflowError | 栈溢出 | 无限递归 |
| Direct buffer | 直接内存溢出 | NIO 未释放、Netty 用量大 |
二、GC 调优思路
- 选收集器:大堆低延迟选 G1;超大堆(数十 G)且追求极致停顿选 ZGC / Shenandoah;
- 定堆大小:
-Xms与-Xmx设成一致避免动态扩缩; - 看 GC 日志:开
-Xlog:gc*,关注 Full GC 频率与停顿时长; - 降对象存活:缓存用弱引用、及时释放大集合,比调参更根本。
三、排查工具链
jps -l # 看 Java 进程
jstat -gcutil <pid> 1s # 实时看 GC 各分区占用
jmap -histo <pid> | head # 按类看对象数量/大小
jstack <pid> > t.txt # 导出线程栈,查死锁/卡点
# Arthas:线上不停机诊断
arthas > thread -b # 找阻塞线程
arthas > dashboard # 实时面板
四、典型排查流程
- 看监控:CPU、内存、GC 是否异常;
jstat确认是否频繁 Full GC;jmap -histo找占用最大的类,定位泄漏点;jstack/ Arthas 看是否死锁或某线程长期 RUNNABLE 占用 CPU;- 结合代码 + 堆转储(
jmap -dump)用 MAT 分析引用链。
JVM 调优的精髓是”先量化再调”:用工具拿到 GC 和内存的真实数据,而不是凭感觉加 -Xmx。