JVM:使用 MAT 工具结合jmap命令分析内存泄漏

1、下载MAT工具

2、演示内存溢出

  • 新建一个springboot项目,新建一个controller
@RestController
public class HeapControler {

    private ArrayList<User> arrayList = new ArrayList<User>();
  
    @GetMapping("/heapmmo")
    public void heapDemo(){
        while (true) {	//死循环导致内存溢出
            arrayList.add(new User("213","231"));
        }
    }
    
}

3、使用 jmap 导出内存映像文件

  • 打开cmd,进入桌面
    JVM:使用 MAT 工具结合jmap命令分析内存泄漏

  • 执行命令 jps,查看springboot项目的进程号
    JVM:使用 MAT 工具结合jmap命令分析内存泄漏

  • 可以发现springboot进程号是 14036,执行命令jmap -dump:format=b,file=a.hprof 14036
    JVM:使用 MAT 工具结合jmap命令分析内存泄漏

  • 桌面会生成一个 a.hprof 的文件

4、使用 MAT 打开,File —> open file —> a.hprof
JVM:使用 MAT 工具结合jmap命令分析内存泄漏

可以发现可能导致的问题有两个,然后分析这两个问题:
JVM:使用 MAT 工具结合jmap命令分析内存泄漏
首先第一个,点击 details
JVM:使用 MAT 工具结合jmap命令分析内存泄漏
通过第3行,基本上能够定位到我们的 controller。

  • 另外,我们可以点击左上角第二个图标,通过对象数量定位异常
    JVM:使用 MAT 工具结合jmap命令分析内存泄漏
    在第一行输入匹配规则,我们匹配我们自己的项目 com.eaphy ,可以看出User类的数量达到了46万多个,肯定是不正常的。
    然后,右键User,找到是哪个GC Roots引用了该对象
    JVM:使用 MAT 工具结合jmap命令分析内存泄漏

JVM:使用 MAT 工具结合jmap命令分析内存泄漏
可以清楚的看到,是HeapControler 里面的 arraylist。

  • 另外,我们可以点击左上角第三个图标,通过对象占内存的百分比定位异常

JVM:使用 MAT 工具结合jmap命令分析内存泄漏
第一个和其他比起来,明显占比太大,可能不正常,然后,展开该行数据,定位到具体文件
JVM:使用 MAT 工具结合jmap命令分析内存泄漏