MAT使用指南

Memory Analyzer (MAT)

The Eclipse Memory Analyzer is a fast and feature-rich Java heap analyzer that helps you find memory leaks and reduce memory consumption.

安装

官网地址:https://www.eclipse.org/mat/

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/bb51587c28b3457fa27a40c523828dec~tplv-k3u1fbpfcp-watermark.image

目前MAT已经迭代到了1.12.0版本, 已经支持解析OpenJDK 15的堆信息。

需要注意的是,MAT本身也是java应用,运行所需的最低java版本已经是Jdk 11了。

配置

https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8d5813f52687400097a529138e81079e~tplv-k3u1fbpfcp-watermark.image

解压之后,根据自己的电脑配置和堆转储文件的大小,酌情改一下MemoryAnalyzer.ini中的Xmx的大小。

https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/023a40f18f7f4771b30cd91173fe488e~tplv-k3u1fbpfcp-watermark.image

获取堆转储文件

介绍几种方式:

  1. 从服务器上直接dump,一般是联系运维同学帮忙操作,传到本地进行分析。
1
2
3
4
jmap -dump:format=b,file={dumpfile.hprof} {pid}


举例jmap -dump:format=b,file=20210823.hprof 55244
  1. 还可以配置在启动参数上,当发生内存溢出时,会自动dump文件。
1
-XX:+HeapDumpOnOutOfMemoryError
  1. 通过VisualVM,这里建议下载一个idea插件:

https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/22a48cb7f31c440cab41ece4013fc94a~tplv-k3u1fbpfcp-watermark.image

插件安装好之后,可以在debug按钮后面找到新增的两个橘色按钮,和正常的run、debug相比,会在启动的同时打开 Java visualVM。

https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3d52724ddeef4207aa06386c88733930~tplv-k3u1fbpfcp-watermark.image

切换到监视页签,可以点击图示位置的按钮,进行dump操作。

https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3406f2b5fd1e402290326017a32742dc~tplv-k3u1fbpfcp-watermark.image

加载文件

https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a31a5f845a7e4aae931606fa53cf5c9e~tplv-k3u1fbpfcp-watermark.image

这里面最常用的功能就是Histogram、Leak Suspects。

先贴一下代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
@Controller
public class HelloWorldController {

    @GetMapping("index")
    public void index() throws InterruptedException {
        hi();
    }

    public void hi() throws InterruptedException {
        int size = 1024 * 1024;

        List<byte[]> list = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            System.out.println("存放了" + (i + 1) + "M 数据");
            list.add(new byte[size]);
            Thread.sleep(1000);
        }
    }
}

Leak Suspects:

https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/53ee963d1cd644bc85ba8e9dfa5b8e5a~tplv-k3u1fbpfcp-watermark.image

https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7a315f9de6a8404f894ca68e66a5289c~tplv-k3u1fbpfcp-watermark.image

图中黄色部分是问题描述,一个tomcat任务线程保存了33M的本地变量,Keywords里面甚至给出了具体的类名和行数。

点进详情,还可以查看完整的堆栈信息

https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0eb5001cba614a3099ea905af72ff3f2~tplv-k3u1fbpfcp-watermark.image

Histogram

https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d47cd8d5d4ba46c1840ac6b30a6ffa87~tplv-k3u1fbpfcp-watermark.image

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d11ff197a08042c8a34ff6509f23ce7e~tplv-k3u1fbpfcp-watermark.image

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/641e50e40745486498968b14203a79b1~tplv-k3u1fbpfcp-watermark.image

上面三个步骤,意思是查看排除虚引用/弱引用/软引用等的引用链,因为被虚引用/弱引用/软引用的对象可以直接被GC给回收,我们要看的就是某个对象否还存在Strong 引用链(在导出HeapDump之前要手动出发GC来保证),如果有,则说明存在内存泄漏,然后再去排查具体引用。

可以清楚的看到List里面,33个byte数组,每个占用1M内存。

好了,今天就先介绍到这里,我们下期再见👋🏻。