面试知识库

JVM GC → 内存泄漏 → OOM 排查 追问链#

追问路径#

涉及知识点#

核心串联逻辑#

  1. GC基础:Young GC回收Eden区(复制算法,STW通常<50ms),Full GC回收整堆(目标<200ms)
  2. Full GC频繁 = 老年代回收效率低:每次Full GC回收很少空间 → 说明有对象无法回收但持续增长 → 内存泄漏
  3. 排查路径jstat -gcutil pid 1000 看Old区占比和GC后回收率 → dump堆 → MAT的Dominator Tree定位
  4. 堆外泄漏:堆正常但进程RSS持续增长 → NativeMemoryTracking追踪;Netty场景用leak detection
  5. 容器陷阱:-Xmx=容器limit会OOM Killer(没给非堆预留空间),Xmx ≤ 容器内存 × 0.7
  6. 代码示例
    # 一键排查GC状态
    jstat -gcutil <pid> 1000 5
    # 输出: S0 S1 E O M YGC YGCT FGC FGCT GCT
    # 关注: O(老年代)>90%且FGC频繁 → 可能泄漏
    bash

面试回答串联#

30秒速答#

“Full GC频繁通常是内存泄漏导致老年代持续增长。排查路径:jstat确认GC模式,dump堆用MAT分析Dominator Tree找泄漏对象。常见原因有ThreadLocal未remove、静态Map无上限。生产配HeapDumpOnOOM保证第一现场。“

2分钟展开答#

“JVM垃圾回收基于可达性分析+分代回收。Young GC用复制算法回收Eden,STW通常不到50ms;Full GC回收整堆目标控制在200ms内。Full GC频繁说明老年代空间回收效率低——每次GC释放很少但对象持续涌入,典型的内存泄漏信号。我的排查流程:先用jstat -gcutil看Old区占比和Full GC后的回收率,如果每次回收很少说明有泄漏。然后HeapDumpOnOOM自动dump,或用Arthas的heapdump在线导出不需要重启。MAT打开后看Dominator Tree找到占内存最大的对象链,常见根因是ThreadLocal用完没remove(线程池复用线程导致累积)、静态HashMap无上限增长、数据库连接未关闭。如果是堆外内存泄漏(堆正常但进程RSS持续增长),用NativeMemoryTracking追踪,Netty场景开启leak detection。容器环境要注意Xmx不能等于容器limit,要预留30%给线程栈、元空间和堆外内存,否则会被OOM Killer杀掉。“

相关追问链#