首要动作是保留现场并导出堆快照,而非重启;通过-XX:+HeapDumpOnOutOfMemoryError自动触发或jmap手动导出,结合jstat判断泄漏性质,再用MAT/jhat定位异常对象及引用链,最后对照静态集合、ThreadLocal等高频泄漏场景验证修复。

线上Java应用发生OOM,首要动作不是重启,而是保留现场——快速导出堆快照(Heap Dump),再通过分析定位泄漏源头。整个过程可在5分钟内完成,关键在工具链熟练、步骤不跳步。
一、立即导出堆快照的两种可靠方式
生产环境讲究“快、稳、可回溯”,推荐优先使用JVM参数自动触发,辅以手动jmap兜底:
-
方式1:JVM启动时启用自动Dump(最推荐)
在启动脚本中加入:-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/dump/
一旦OOM发生,JVM会自动生成java_pid<pid>.hprof</pid>文件,路径清晰、无需人工干预。 -
方式2:运行中手动触发(适用于未配置自动Dump或OOM未复现)
先查PID:jps -l | grep YourApp
再导出快照:jmap -dump:format=b,file=/data/dump/heap_$(date +%s).hprof <pid></pid>
注意:该操作会短暂STW(Stop-The-World),但对多数服务影响可控;若应用极敏感,可加-F强制执行(需root权限)。
二、用jstat快速判断是否真为内存泄漏
导出前或导出后,先跑一次jstat确认现象性质,避免把正常波动当泄漏:
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
- 执行:
jstat -gcutil <pid> 2000 5</pid>(每2秒采样,共5次) - 重点看
O(老年代使用率)和FGC(Full GC次数):
— 若O持续>95%且FGC频繁上升,GC后内存不回落 → 高概率内存泄漏;
— 若O阶段性冲高但GC后能回落至60%以下 → 更可能是业务峰值或缓存合理增长。
三、用MAT快速定位泄漏对象(不依赖图形界面也可行)
拿到.hprof文件后,不必等MAT图形界面,命令行+基础分析就能锁定目标:
立即学习“Java免费学习笔记(深入)”;
- 先用
jhat快速过一遍(JDK自带,适合无GUI服务器):jhat -port 7000 heap_1734235600.hprof,然后浏览器访问http://server:7000,点“Show heap histogram”看类实例数TOP榜。 - 重点关注三类异常信号:
— 某个自定义类(如com.xxx.UserCache)实例数达数十万;
—byte[]、char[]或大集合(ArrayList、HashMap)总占比超30%;
— 存在强引用链指向“疑似已失效对象”(如监听器、ThreadLocal、静态Map中的value)。
四、对照高频泄漏场景反向验证
分析出可疑类后,直接查代码是否落入经典陷阱:
-
静态集合未清理:检查
static Map/ConcurrentHashMap/List是否只增不删,尤其缓存类; -
ThreadLocal未remove:线程池场景下,务必在
finally块调用threadLocal.remove(); -
资源未关闭:数据库连接、文件流、NIO的
ByteBuffer.allocateDirect()是否漏了close()或clean(); -
监听器未注销:GUI或事件驱动框架中,注册后生命周期结束时是否调用
removeListener。

















