Skip to content

MAT分析内存快照

  • MAT是Eclipse开发的Java堆内存图形化分析工具, 注意下1.11版本的(更高版本需要JDK1.8以上)

下载链接: https://eclipse.dev/mat/previousReleases.php

  • 使用jmap -dump:live,file=<fileName.hprof> <PID>生成堆转储快照, -dump:live 参数只打印堆中存活的对象, 即会触发FGC
  • 程序启动时, 添加jvm参数-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/app/logs/app.dump能在OOM时自动记录dump文件

MAT使用简要说明

核心概念

  • 浅堆(shallow heap), 指的是一个对象本身所占用的内存
  • 保留集(Retained Set), 对象所持有的其他对象的集合
  • 深堆(Retained Heap), 指对象的保留集中所有对象浅堆大小之和
  • 支配树(Dominator Tree), 体现对象实例间的支配关系, 如下右图是左图的支配树

1745408628569

使用指南

  • 拿一个OOM的堆快照做简要演示
java
/**
     * -Xmx10m
     * -Xms10m
     * -XX:+HeapDumpOnOutOfMemoryError
     * -XX:HeapDumpPath=C:\xz\temp\
     * -XX:+PrintGCDetails
     * -XX:+PrintGCTimeStamps
     * -XX:+UseConcMarkSweepGC 使用CMS
     * -XX:CMSInitiatingOccupancyFraction=70 CMS当老年代内存使用达到70%时进行垃圾回收(默认92%)
     * -XX:+CMSParallelRemarkEnabled CMS并行运行最终标记阶段
     * -XX:+UseCMSInitiatingOccupancyOnly 虚拟机会根据收集的数据决定是否触发gc
     */
    public static void main(String[] args) throws InterruptedException {
        ArrayList<byte[]> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            list.add(new byte[1024 * 1024 * 5]);
        }
    }
  • Leak Suspects, 打开dump文件后, 会自动检测可疑的内存泄漏点

1745408642859

  • Histogram, 以直方图显示堆内存使用情况

1745408649334

  • 按深堆倒序, 查看到26个byte[]对象却占有5M的内存, 排序靠前, 右键List objects--with incomong references(显示持有它的上级对象, outgoing则是显示它持有的下级对象)

1745408655600

  • 可以看到main线程里, 有个数组, 持有该字节对象, 再结合具体代码分析

1745408661843

  • 也可以直接展示支配树

1745408667891

  • 也能直接看到占用内存较大的字节数组

1745408674136

参考