直接回答:流程四步:拿 dump(jmap -dump:live,format=b 或 -XX:+HeapDumpOnOutOfMemoryError 自动落盘;容器环境注意 dump 文件比堆大、磁盘要够);MAT 打开先跑 Leak Suspects 报告;用 Histogram 按 retained heap 排序找大户;对可疑对象用 Path to GC Roots(排除软/弱/虚引用)看谁在拽着它不放。泄漏的定位本质是找到那条“不该存在的引用链”。

展开解析:关键概念:shallow heap(对象自身大小)vs retained heap(对象被回收后连带释放的总量)——泄漏分析只看 retained;Dominator Tree 视图把堆按“支配关系”组织,泄漏者通常是一个 retained 巨大的支配节点(典型:一个静态 Map、一个 ThreadLocal、一个没关闭的缓存)。高频泄漏指纹:static 集合只增不减;ThreadLocal 在线程池里没 remove(线程复用导致永远可达);监听器/回调注册后忘反注册;ClassLoader 泄漏(热部署、Groovy/JS 引擎反复加载类,Metaspace 涨而非堆涨);连接/流未关闭挂着的缓冲。大堆 dump(几十 GB)分析技巧:先用 jhat 已淘汰、用 MAT 的索引预计算或 Eclipse MAT 服务器模式,或用 JMC 的 JOverflow 找冗余占用(装箱、重复字符串、空集合浪费)。预防侧:线上常驻 1%~2% 内存的分配采样(JFR jdk.ObjectAllocationSample),泄漏苗头在 OOM 前几周就能从趋势里看见。

追问方向:什么情况下 retained heap 会误导判断?Metaspace 泄漏怎么查?

(约 480 字)