记一次 OOM 问题排查:从 hprof 文件到问题根源
服务出现java.lang.OutOfMemoryError: Java heap space错误,导致服务需要重启。本文记录了完整的排查过程,重点分享如何生成和分析 hprof 文件,以及使用 Memory Analyzer 工具定位问题的实战经验。
一、问题现象与初步判断
故障表现为:点击界面某个按钮后,完全无响应,日志中出现 OOM 错误。通过k8s监控平台观察到,内存使用率上升。
为了进一步分析,我们需要获取内存快照(hprof 文件),这是定位 OOM 问题的关键依据。
二、生成 hprof 文件:捕捉内存快照
启动参数预设
在应用启动时添加如下 JVM 参数,当 OOM 发生时会自动生成 hprof 文件:
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/logs/abc.hprof
三、使用 Memory Analyzer 分析 hprof 文件
Memory Analyzer(简称 MAT)是一款强大的 Java 内存分析工具,能帮助我们快速定位内存泄漏点。
1. 工具准备
- 下载地址:Eclipse MAT 官网
2. 基本分析流程
(1)导入 hprof 文件
启动 MAT 后,选择File -> Open Heap Dump,导入生成的 hprof 文件。首次打开会进行解析,较大的文件可能需要几分钟时间。
(2)生成内存报告
解析完成后,MAT 会自动生成一个摘要报告(Overview),包含以下关键信息:
- 总内存占用
- 最大对象
- 线程信息
- 可能的内存泄漏点(Leak Suspects)
- 最大对象占用内存比例较高:从 “Biggest Objects by Retained Size” 的饼图能看到,
java.lang.Thread @ 0xf1fa03b0 EVENTMDC-Executor-2这个线程的 Retained Size 达到了 375.4 MB,占总内存 486.1 MB 的很大比例。
(3)定位大对象
通过**Dominator Tree**功能展示出最大的对象以及它们所引用的对象
在本次分析中,发现
java.util.ArrayList以及大量的UserDataPermission对象也占用了较多内存。这提示可能存在与该线程相关的内存使用问题,比如线程执行过程中,相关集合(如这里的 ArrayList)持有大量UserDataPermission对象且未及时释放,进而可能引发内存泄漏或内存不足问题。
四、问题解决与验证
根据分析结果,我们修复了逻辑的 bug,减少了ArrayList的内存占用。
部署后在界面点击不再出现oom问题。