背景
最近功能模块上线后,生产内存占用显著提升,查看gc日志发现年轻代频繁从2G回收到60M左右,猜测是在方法中频繁创建大对象导致,由于一时间无法通过review代码找出问题所在,只好将生产jvm内存快照dump后通过java memory analyzer tool进行分析。
介绍
MAT(java memory analyzer tool)是一款基于eclipse免费开源的java内存分析工具,可以用来分析java堆栈溢出,大对象排查等。
下载安装
https://www.eclipse.org/mat/previousReleases.php
使用
- 前往服务器dump出jvm内存快照
命令:jmap -dump:all,format=b,file={快照保存文件名}.hprof {应用pid},dump:all表示dump出所有对象,如jmap -dump:all,format=b,file=jvmall.hprof 3314 - 修改mat jvm参数,增加最大堆内存,避免打开大快照出现oom问题
- 打开mat软件,进行自定义设置
设置保留不可达对象,对象占用内存单位根据大小自动按照byte/mb等显示
- 选择dump出来的jvm快照
依次点击file -> open heap dump
选择泄露检查,点击完成,等待快照加载完毕
点击查看对象柱状图
根据对象存在堆中的大小进行排序
右键查看大对象集合的引用情况
再次按照对象大小进行排序查看,找到大对象的引用关系,由于有的大对象的引用已被gc回收,因此无法找到具体的引用根节点,需要我们手动筛选下。
从上图可以看出,堆中存在大量base64编码的图片字符串大对象,通过引用关系可以定位到引用到这些大对象的model类,再结合代码最终解决问题。 - 修改mat设置后(如从保留不可达对象到只分析可达对象),需要删除上次打开生成的分析文件,再重新启动mat