java内存性能优化工具Mat
1.MAT(Memory Analyzer Tool)工具是一款功能强大的]ava堆内存分析器。可以用于查找内存泄漏以及查看内存消耗情况。MAT是基于Eclipse开发的,不仅可以单独使用,还可以作为插件的形式嵌入在Eclipse中使用。是一款免费的性能分析工具,使用起来非常方便。
2.下载地址
https://eclipse.dev/mat/download/
我这边电脑的系统是window系统,jdk版本是1.8,下载时应选择对应的版本下载
3.安装
双击启动MemoryAnalyzer.exe启动
如果启动报错,出现Incompatible JVM 弹窗时,下载弹窗中指定的jdk版本,不需要安装解压后在MemoryAnalyzer.ini 中通过加入以下内容加入指定jdk的地址
-vm
D:/java/jdk1.8.0_211/bin/javaw.exe
4.使用
点击左上角file,选择所要打开的分析文件
如果堆dump文件较大、使用MAT打开的时候总是抛出 Java Heap Error
解决办法:
找到MAT的安装目录,找到MemoryAnalyzer.ini 修改其中的-Xmx即可
5.获取dump文件
通过top -c(然后按Shift+M按内存排序)命令找到占用内存大的java进程,通过以下命令生成dump文件
- jmap -dump:format=b,file=oom.hprof 进程ID
通常情况下,在生产环境中使用jmap命令生成Heap dump文件时,建议把生成的文件下载到本地进行分析,以减少对生产环境的干扰。另外,在生成Heap dump文件时,一定要确保Java应用程序正常运行,否则可能会导致生成的文件不完整或者无法正确解析。
二、MAT工具排查分析
1.使用MAT定位问题
定位问题方式一:
现在有一个OOM
后得到的堆转储文件 oom.hprof,现在要使用 MAT 的直方图
、支配树
、线程栈
、OQL
等功能来分析此次 OOM 的原因。
首先,用 MAT 打开后先进入的是概览信息界面,可以看到整个堆是 51MB:
那么,这 51MB 都是什么对象呢?
如图所示,工具栏的第二个按钮可以打开直方图,直方图按照类型进行分组,列出了每个类有多少个实例,以及占用的内存。可以看到,char[]字节数组占用内存最多,对象数量也很多,结合第二位的 byte[] 字节数组数量也很多,大概可以猜出程序可能是char[]和byte[]作为实际数据存储占满了内存,导致 OOM。
在 char[]
上点击右键,选择 List objects->with incoming references
,就可以列出所有的 char[]
实例,以及每个 char[]
的整个引用关系链:
- Shallow Heap(浅堆)指对象自身占用内存的大小,包括对象头和成员变量(但不包括成员变量的值)
- Retained Heap(深堆/保留堆)指对象被回收后,所有因引用关系被释放的对象所占内存总和。
找到Shallow Heap占用最大的一个 char[]展开,如下图所示:
可以大概知道我这个项目中write占用过多的内存,但是还是不能具体到那个具体的程序。
定位问题2:
点击工具栏中第三个按钮(下图左上角的红框所示)进入支配树界面。这个界面会按照对象的 Retained Heap
倒序直接列出占用内存最大的对象。
从上面的具体信息中可以看到序列化,缓存,数据库初始化所占用的内存较大,但是还是不能定位到具体的程序。
定位问题3:
点击工具栏的第五个按钮(下图红色框所示)。打开线程视图
通过以上信息可以看出我的程序中产生了很多定时程序的线程,从而占用了大量内存。
然后可以通过搜索查看引用的对象
点击工具栏的第四个按钮(如下图红框所示),来到 OQL 界面。在这个界面,我们可以使用类似 SQL 的语法,在 dump 中搜索数据(你可以直接在 MAT 帮助菜单搜索 OQL Syntax,来查看 OQL 的详细语法)。
sql:
- select * from org.apache.tomcat.util.threads.TaskThread
点击下图中红色叹号按钮,运行上记sql,查找对象
定位问题4:
点击工具栏的第一个按钮(如下图红框所示),进入Leak Suspects界面
Leak Suspects 是 Eclipse Memory Analyzer (MAT) 工具的核心功能之一,用于快速定位 Java 堆转储文件中的内存泄漏嫌疑对象。
点击Details,查看详情
通过上述信息可以看出我的项目中定时任务占用了大量内存
通过查找代码,发现我启动了很多的定时任务
通过分析优化掉不需要的定时任务,可以释放一些内存。