本文总结了排查内存溢出问题的MAT工具,先来看看本文目录:
给,你们想要的内存溢出 MAT 排查工具
Java 堆内存分析工具。
1@RestController
2public class MatController {
3
4 List
5
6 @GetMapping("/mat")
7 public String mat() {
8 for (int i = 0; i < 10000000; i++) {
9 User user = new User();
10 user.setId(1L);
11 user.setUserName("老田" + i);
12 list.add(user);
13 }
14 return "ok";
15 }
16}
设置JVM启动参数
1-Xms20m -Xmx20m -XX:MaxPermSize=20m -XX:+HeapDumpOnOutOfMemoryError
访问http://localhost:8080/mat
不过一会就报异常了。然后
给,你们想要的内存溢出 MAT 排查工具
与之同时,生成了一个文件
给,你们想要的内存溢出 MAT 排查工具
实战MAT
下载地址:
http://www.eclipse.org/mat/downloads.php
给,你们想要的内存溢出 MAT 排查工具
下载到本地并解压
给,你们想要的内存溢出 MAT 排查工具
双击MemoryAnalyzer.exe打开
给,你们想要的内存溢出 MAT 排查工具
我们把前面生成的java_pid4928.hprof文件导入进来
给,你们想要的内存溢出 MAT 排查工具
点击finish
给,你们想要的内存溢出 MAT 排查工具
给,你们想要的内存溢出 MAT 排查工具
我的天啦,立刻就把我们问题定位到了,MatController这个类的嫌疑最大(其实线上环境一般都不会这么容易)。
给,你们想要的内存溢出 MAT 排查工具
点击图中的最大区域
给,你们想要的内存溢出 MAT 排查工具
outgoing references 对象的引出
incoming references 对象的引入
另外Path to GC Roots这是快速分析的一个常用功能,显示和 GC Roots 之间的路径。
树状图
左上角 有个图标,树状图
给,你们想要的内存溢出 MAT 排查工具
进入树状图
给,你们想要的内存溢出 MAT 排查工具
一眼就知道我们的MatController有问题,居然排在最前面了。另外两个关键属性:
Shallow Heap:浅堆,表示对象本身的内存占用。
Retained Heap:深堆,表示对象自身的内存占用
而且在MatController类上还有个Regex,支持正则表达式,于是我就输入了我特有的命名tian,按下回车键:
给,你们想要的内存溢出 MAT 排查工具
然后,便把tian相关的全部输出。
同理,如果我们在排查线上问题是,也可以输入我们特有关键字等来快速定位问题。每个公司基本上都有自己一套独立的包目录。我们就可以使用那个特有的关键字进行搜索。
点开MatController类,下面有个List,然后List存了User对象,这不就是我们上面的代码么?
给,你们想要的内存溢出 MAT 排查工具
柱状图
同样在左上角有个柱状图
给,你们想要的内存溢出 MAT 排查工具
点击进去
给,你们想要的内存溢出 MAT 排查工具
看到第一行有Regex,哈哈,又是支持正在表达式,我们再次输入tian关键字。
给,你们想要的内存溢出 MAT 排查工具
并且我们发现
1com.tian.dto.User
对象个数是132033个。
OQL
MAT 支持一种类似于 SQL 的查询语言OQL(Object Query Language),这个查询语言 VisualVM工具也支持。
OQL将类表示为表,对象表示为行,字段表示为列。
语法:
1SELECT *
2FROM [ INSTANCEOF ]
3[ WHERE
4
用F5或者Ctrl+enter或者点击红色的感叹号立即执行OQL。
给,你们想要的内存溢出 MAT 排查工具
输入关键词还可以提示:
给,你们想要的内存溢出 MAT 排查工具
查询结果
给,你们想要的内存溢出 MAT 排查工具