Skip to content

Java内存泄漏排查完整思路

一、常见OOM异常分类

  1. java.lang.OutOfMemoryError: Java heap space 堆内存泄漏,长期存活对象无法被GC回收,占用堆空间持续上涨。
  2. OutOfMemoryError: Metaspace 元空间溢出,动态加载大量类、反射频繁创建类未卸载。
  3. StackOverflowError 虚拟机栈溢出,递归过深、局部变量过多、-Xss栈内存设置过小。

二、整体排查四步流程

  1. 获取堆内存快照dump文件
  2. 使用VisualVM离线加载dump
  3. 分析堆快照,定位大对象、引用链、报错堆栈
  4. 定位业务代码,修复内存泄漏逻辑

三、第一步:获取堆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

  1. 打开jvisualvm.exe;
  2. 顶部菜单【文件】→【装入】;
  3. 选中导出的heap.hprof文件加载;
  4. 切换「概要、类、实例、OQL」面板分析。

五、第三步:dump文件核心分析要点

  1. 概要面板:查看OOM报错线程、抛出异常的方法栈,直接定位出错代码行;
  2. 类面板:按实例数量/占用内存排序,找出占用最大的自定义业务对象;
  3. 实例面板:查看对象引用链,判断是谁长期持有对象导致无法GC;
  4. 对比多次dump快照,观察对象持续增长的类型,确认泄漏对象。

六、第四步:代码修复

根据引用链、堆栈信息定位泄漏代码,常见泄漏场景:

  1. 静态集合长期存放对象(static List/Map);
  2. ThreadLocal使用后未调用remove();
  3. 缓存无过期淘汰策略,无限堆积数据;
  4. IO、连接未关闭,持有大对象引用;
  5. 循环创建大量对象未释放。

七、面试简答

问:线上Java发生内存泄漏/OOM,完整排查思路是什么?

答:

  1. 提前配置JVM参数-XX:+HeapDumpOnOutOfMemoryError,OOM时自动生成堆dump;若未配置,程序运行时用jmap手动导出hprof快照。
  2. 使用VisualVM离线加载dump文件,查看OOM异常堆栈定位报错代码,同时查看实例占用排序,找出持续增长的对象。
  3. 分析对象引用链,确定长期持有对象、阻止GC回收的代码位置。
  4. 修复对应业务代码,比如清理静态容器、ThreadLocal用完remove、缓存增加淘汰机制,重新发布验证内存稳定。

Powered by VitePress 1.6.4 | 持续更新中