背景:生产环境有一个程序突然挂掉了,进去控制台没有任何反应,看到服务器已经生成了hprof文件,hprof后缀文件是堆内存溢出导致程序挂掉时保存的快照,但是是什么原因导致程序内存溢出的呢?记录一下分析hprof文件的流程笔记
注:
hprof是什么文件?
是java进程的内存镜像文件,里面包含了内存堆详细的使用信息,即某个时间点的java进程的内存快照
一、下载Memory Analyzer软件
Eclipse Memory Analyzer(MAT)是一款内存分析工具
二、Memory Analyzer简单使用
上图最中央的那个饼状图展示了最大的几个对象所占内存的比例
底部有几个核心的菜单按钮
- Histogram:可以列出内存中每个对象的名字、数量以及大小。
- Dominator Tree:会将所有内存中的对象按大小进行排序,并且可以分析对象之间的引用结构
- Top Consumers:通过图形列出最大的object以及包路径
- Leak Suspects:分析内存泄漏的可能原因
- Top Components: 列出大于总堆1%内存的对象
三、分析hprof文件
1)首先把服务器生成的这个hprod后缀的文件下载到本地电脑,通过sz命令
2)打开Memory Analyzer,点击Open Heap Dump选中hprof文件
3)装入hprod文件后如图
从饼状图很明显就看出问题了,有对象占用了极大内存
4)点击Dominator Tree,看看那些对象占用内存排序以及关联对象之间的引用
从图中可以看到是一个线程占用了93%的内存,这线程里面关联了TreeMap以及poi的XSSFRow对象(暂时还分析不出原因)
注:
- Shallow Heap:就是对象本身占用内存的大小,不包含对其他对象的引用,也就是对象头加成员变量(不是成员变量的值)的总和。
- Retained Heap:是该对象自己的shallow size,加上从该对象能直接或间接访问到对象的shallow size之和。换句话说,retained size是该对象被GC之后所能回收到内存的总和。
- 重点是看Retained Heap,Retained Heap表示GC能回收到的内存
5)点击Leak Suspects,查看内存泄漏原因
分析:可以看出是某一个线程占用了大量内存,这个线程了有很多TreeMap对象,看到还有poi对象,可能是导出excel表格相关的操作导致的(用户的一个请求就是一个线程,有可能是用户在进行导出数据)
6)再点上图的See stacktrace
从这个异常栈可以定位到出错的代码位置,可以看到出错的位置是AssetBaseQueryController.export的方法,这个方法是我们使用poi导出excel的函数,里面使用了poi,poi的XSSFRow对象里面使用了TreeMap,结合上面的分析,错误原因就可以知道,是用户的一个请求在导出excel数据,而这个导出耗尽了内存,所以是在一个线程里面使用了大量的TreeMap,但是内存耗尽,所以程序挂掉了,也没办法触发GC回收了
四、解决方案
原因是由于导出的数据比较大量,大概有10w行 * 50列,由于后台直接用XSSFWorkbook导出,在导出结束前内存有大量的Row,Cell,Style等,以及基于XLSX底层存储的XML对象没有被释放。
使用EasyExcel替换原来的poi导出方法
EasyExcel是阿里巴巴开源的一个excel处理框架,以使用简单、节省内存著称
EasyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。
到此这篇hprof文件分析内存问题(hprof文件怎么产生的)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/rfx/51963.html