主题切换
Java内存泄漏排查完整思路
一、常见OOM异常分类
java.lang.OutOfMemoryError: Java heap space堆内存泄漏,长期存活对象无法被GC回收,占用堆空间持续上涨。OutOfMemoryError: Metaspace元空间溢出,动态加载大量类、反射频繁创建类未卸载。StackOverflowError虚拟机栈溢出,递归过深、局部变量过多、-Xss栈内存设置过小。
二、整体排查四步流程
- 获取堆内存快照dump文件
- 使用VisualVM离线加载dump
- 分析堆快照,定位大对象、引用链、报错堆栈
- 定位业务代码,修复内存泄漏逻辑
三、第一步:获取堆dump快照(两种方案)
方案1:运行时手动导出(程序还未崩溃)
使用jmap命令抓取进程堆快照
shell
jmap -dump:format=b,file=heap.hprof <pid>方案2:JVM参数自动生成(推荐线上配置)
程序OOM崩溃时自动dump,避免进程直接退出抓不到快照,启动参数添加:
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/home/app/dumps/- HeapDumpOnOutOfMemoryError:OOM触发自动导出堆快照
- HeapDumpPath:指定dump文件存储目录
四、第二步:VisualVM加载离线dump
- 打开jvisualvm.exe;
- 顶部菜单【文件】→【装入】;
- 选中导出的heap.hprof文件加载;
- 切换「概要、类、实例、OQL」面板分析。
五、第三步:dump文件核心分析要点
- 概要面板:查看OOM报错线程、抛出异常的方法栈,直接定位出错代码行;
- 类面板:按实例数量/占用内存排序,找出占用最大的自定义业务对象;
- 实例面板:查看对象引用链,判断是谁长期持有对象导致无法GC;
- 对比多次dump快照,观察对象持续增长的类型,确认泄漏对象。
六、第四步:代码修复
根据引用链、堆栈信息定位泄漏代码,常见泄漏场景:
- 静态集合长期存放对象(static List/Map);
- ThreadLocal使用后未调用remove();
- 缓存无过期淘汰策略,无限堆积数据;
- IO、连接未关闭,持有大对象引用;
- 循环创建大量对象未释放。
七、面试简答
问:线上Java发生内存泄漏/OOM,完整排查思路是什么?
答:
- 提前配置JVM参数
-XX:+HeapDumpOnOutOfMemoryError,OOM时自动生成堆dump;若未配置,程序运行时用jmap手动导出hprof快照。 - 使用VisualVM离线加载dump文件,查看OOM异常堆栈定位报错代码,同时查看实例占用排序,找出持续增长的对象。
- 分析对象引用链,确定长期持有对象、阻止GC回收的代码位置。
- 修复对应业务代码,比如清理静态容器、ThreadLocal用完remove、缓存增加淘汰机制,重新发布验证内存稳定。