Java 面试题:JVM 调优与 OOM 故障排查

一、常见 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      # 实时面板

四、典型排查流程

  1. 看监控:CPU、内存、GC 是否异常;
  2. jstat 确认是否频繁 Full GC;
  3. jmap -histo 找占用最大的类,定位泄漏点;
  4. jstack / Arthas 看是否死锁或某线程长期 RUNNABLE 占用 CPU;
  5. 结合代码 + 堆转储(jmap -dump)用 MAT 分析引用链。

JVM 调优的精髓是”先量化再调”:用工具拿到 GC 和内存的真实数据,而不是凭感觉加 -Xmx。