服务器内存爆炸,日志无报错,通过分析 Dump 文件查找问题原因
背景
Java 项目部署到服务器后,有一个生成 Excel 文件的方法,在生成文件过程中,会导致服务器内存占用率达到 99%,严重影响其他业务的正常进行,代码无报错,需要根据 dump 文件进行分析,查看是否有大内存类对象没有及时释放导致的内存占用问题
前提准备
使用命令将 dump 日志文件下载到本地:
# jmap -dump:format=b,file=D:/tmp/heapdump_20250918.hprof xxx
参数解释:
file : 指定文件的路径,生成的 dump 文件保存到该地址
xxx : 当前进程的 pid
如何查看进程的 pid 命令:
# jps -l
分析过程
获取到我们需要的 dump 文件(上文中我们通过命令下载到指定路径的,后缀名为 .hprof 的文件)后,我们需要借助工具来对该文件进行分析。
这里我们使用 Eclipse MAT(Memory Analyzer Tool) 来对文件进行分析。
如何获取 Eclipse MAT 工具请自行百度即可。
- 通过 mat 工具,我们打开刚获取到的 dump 文件(打开路径:File -> Open Heap Dump,选择我们的文件即可)
- 我们发现,有一块地方占比非常大,达到了 2.1G 内存,那么我们就可以对该快占比区域进行进一步分析
- 展开 Dmoinator Tree ,进一步分析文件
我们可以看到,这里是按照内存占比将不同类文件进行了排序。通过所在类名我们可以看到,占用内存最大是一个对 excel 文件处理的类:XSSFWorkbook,经常接触文件读取的开发者应该知道,这个是一个 POI 包下的核心类,在我们对文件进行读取后,读取的文件的所有信息都将显示在这个类中。通过对下级类名的进一步分析,我们可以看见下面有很多个的 XSSFSheet,我们可以知道,我们读取的这个 excel 文件是包含很多个 sheet 页的,有的 sheet 页可能数据量很大,所以占用了很多的内存。这个也是服务器内存直接被占满的主要原因。
- 知道了内存被占用的位置,我们针对内存占用大的地方进行代码的优化即可,使用不同的文件处理工具(最原始的就 POI,常用的开源工具类有阿里的 EasyExcel,以及后面新开源的 FastExcel 都可以)有不同的解决方案,这里就不再做具体的解决方案了。