Prompts-MCP 686 skills · ai / design / design-pattern / framework / fundamentals / habit / lang / tech-selection /mcp/sse
fundamentals fundamentals/troubleshooting/memory-leak.md high

troubleshooting-memory-leak

内存泄漏/OOM 定位 — jmap dump 堆快照,用 MAT 看支配树和最大对象,沿 GC Roots 引用链找住对象不放的根因。Use when 内存持续上涨 / 抛 OutOfMemoryError / 分析堆 dump 找泄漏对象时。

内存泄漏oomjmap堆 dumpmat支配树
paths
  • *.java

线上排查 · 内存泄漏 / OOM 定位

本条只管「内存涨/OOM 怎么找泄漏对象」。CPU 高见 cpu-high.md;OOM 的类型分流(堆/元空间/栈/直接内存)见 ../jvm/oom-troubleshooting.md;不确定先看 diagnosis-decision-tree.md

排查步骤(dump → MAT → 引用链)

步骤 手段 拿到什么
1. 拿堆快照 jmap -dump:live,format=b,file=heap.hprof <PID> hprof 文件
1'. OOM 自动落盘 启动加 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=... 崩溃现场 dump
2. 看谁占最多 MAT → Histogram / Dominator Tree(支配树) 最大对象/类
3. 找为何不回收 选中大对象 → Path to GC Roots(exclude weak/soft) 谁在强引用它
4. 看泄漏嫌疑 MAT → Leak Suspects 报告 自动给出嫌疑点

核心思路:支配树告诉你"哪个对象撑大了堆",Path to GC Roots 告诉你"它为什么没被回收"——两者结合才是根因。

正例

# live 只 dump 存活对象,会先触发一次 Full GC(生产慎用,会停顿)
jmap -dump:live,format=b,file=/tmp/heap.hprof 12345
MAT Dominator Tree 典型泄漏画像:
  HashMap                 1.2 GB   <- 一个 Map 占了大半个堆
   └ 持续 put 不 remove 的本地缓存
  Path to GC Roots: static CacheHolder.MAP  <- 静态字段强引用,永不回收

常见根因:无界本地缓存 / static 集合只增不减 / ThreadLocal 未 remove / 监听器未注销。

反例

❌ 内存涨就调大 -Xmx 了事 —— 泄漏没解决,只是更晚 OOM,且 dump 更大更难分析
❌ 不加 -XX:+HeapDumpOnOutOfMemoryError —— OOM 崩了没现场,只能干等复现
❌ 生产高峰直接 jmap -dump:live —— live 触发 Full GC + STW,可能压垮服务(低峰或备机做)
❌ 只看 Histogram 不看 Path to GC Roots —— 知道谁大却不知道谁在引用,改不对

自检

  • [ ] 启动参数加了 -XX:+HeapDumpOnOutOfMemoryError(OOM 自动留现场)?
  • [ ] 用 MAT 支配树找最大对象,而不是只看类直方图?
  • [ ] 对大对象查了 Path to GC Roots 找到强引用源?
  • [ ] 没有用「调大堆」掩盖泄漏?没在生产高峰用 -dump:live 触发 STW?

相关