Java 内存溢出(二)使用 MAT 分析 .hprof 内存映像文件

.hprof 文件: 是 java 项目的 Heap Dump 文件,也叫内存映像文件、内存快照文件,可以存放一个 java 进程在某个时间点的内存快照。生成 Heap Dump 文件的方式有两种:一是使用 jmap 命令手动导出,二是启动脚本中添加 -XX:+HeapDumpOnOutOfMemoryError 参数自动导出。本文中只涉及第二种。

一、内存溢出时自动导出 .hprof 文件

1.新建一个文本文件,命名为 HeapOOM.java,内容如下:

import java.util.ArrayList;
import java.util.List;

public class HeapOOM {
    static class User {}
    public static void main(String[] args) {
        List<User> list = new ArrayList<>();
        while (true) {
            list.add(new User());
        }
    }
} 

2.打开控制台,执行如下命令编译 java 文件:

javac HeapOOM.java

3.使用如下命令运行 java 文件:

java -Xms10M -Xmx10M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./ HeapOOM
  • -Xms10M 堆内存最小10M;
  • -Xmx10M 堆内存最大10M;
  • -XX:+HeapDumpOnOutOfMemoryError 内存溢出时自动导出堆内存快照;
  • -XX:HeapDumpPath=./ 内存快照保存位置,不指定默认当前路径

请添加图片描述

二、下载安装 MAT

下载地址: https://www.eclipse.org/mat/downloads.php

在这里插入图片描述

点击 Download。

在这里插入图片描述

注意:目前最新的版本 Memory Analyzer 1.13.0 Release,是只支持在 JDK 11 下运行的

如果想下载 JDK8 下运行的版本,可以点击 Other Releases > Previous Releases。

请添加图片描述

选择版本:Memory Analyzer 1.9.2 Release

请添加图片描述

三、启动 MAT

双击 exe 文件启动:

请添加图片描述

请添加图片描述

注意: 如果 hprof 文件太大,需要调整它的内存才可以完成大 dump 文件的加载,这个配置文件需要 exe 启动后会自动生成:

请添加图片描述

请添加图片描述

四、MAT 分析 hprof 文件

点击 Open a Heap Dump,选择一个 hprof 文件打开:

请添加图片描述

1.Overview 概览

概览中,我们可以看到对象所占的比例及排序。显然有个对象不正常,一共上限 10M 的内存占用了 6.9 M。

请添加图片描述

2.Leak Suspects 溢出原因猜测

点击下方的 Leak Suspects,可以查看 MAT 的详细分析结果,猜测导致堆栈溢出的原因:

请添加图片描述

请添加图片描述

根据上图可以看到有一个猜测的原因:

  • 主程序占用了 92.88% 的内存,其中 Object 对象过多。

毫无疑问是对象实例过多导致的内存溢出,具体是哪个对象呢,下一步怎么分析呢?

3.Histogram 对象实例数量排序

点击下图所示柱状图(Histogram)查看对象实例数量排序,在 Regex 中可以用输入正则表达式把自己的包名,输入后回车过滤:

请添加图片描述

请添加图片描述

这里的 User 实例有 36w 个,显然不正常,我们可以查下是谁引用的:

请添加图片描述

我们可以看到是 main 线程中引用了这些对象。(当前示例较为简单,如果是项目中可以明确看到是哪个类中的引用导致的)

请添加图片描述

4.Dominator Tree 支配树

支配树: MAT 提供了一个成为支配树(Demonitor Tree)的对象图。支配树体现了对象实例间的支配关系。在对象引用图中,所有指向对象 B 的路径都经过对象 A,则认为对象 A 支配对象 B。如果对象 A 是离对象 B 最近的一个支配对象,则认为对象 A 为对象 B 的直接支配者。

支配树是基于对象间的引用图所建立的,它有以下基本性质:

  • 对象 A 的子树(所有被对象 A 支配的对象集合)标识对象 A 的保留集(Retained Set),即深堆;
  • 如果对象 A 支配对象 B,那么对象 A 的直接支配者也支配对象 B;
  • 支配树的边与对象引用图的边不直接对应。

我们可以理解为支配图就是用来查看类使用内存比例的,图中使用最多的类对应溢出原因猜测中的内存使用率 92.88%。

请添加图片描述

以上就是 MAT 分析 .hprof 文件的常用功能。

整理完毕,完结撒花~





参考地址:

1.导出dump文件及MAT安装分析,https://blog.csdn.net/lixiangchibang/article/details/124721472

2.【JVM笔记】支配树(Dominator Tree),https://blog.csdn.net/lijibai_/article/details/126526375

MAT(Memory Analyzer Tool)是一款用于分析和诊断Java堆转储文件(.hprof文件)的强大工具。通过对.hprof文件分析,可以帮助开发人员定位并解决Java应用程序中的内存问题。 MAT提供了直观的图形界面,用于可视化展示.hprof文件中的对象、类、线程以及引用关系等信息。通过这些信息,可以深入了解应用程序的内存使用情况,包括对象的创建和销毁、引用关系的建立和破坏等。 MAT还提供了各种强大的分析功能,例如:内存泄漏分析、重复对象分析、大对象分析等。这些功能可以帮助开发人员发现内存泄漏问题、优化应用程序的内存使用、减少内存开销等。 在MAT中,我们可以使用一些关键的功能来分析.hprof文件。例如,通过Histogram功能可以查看各个类的实例数量和内存占用情况,以便发现内存占用过高的类。通过Dominators功能可以查找对象之间的引用关系,帮助定位内存泄漏或者无用对象的存在。 此外,MAT还提供了自定义查询功能,使我们可以编写自己的查询脚本来分析.hprof文件。同时,MAT还支持与Eclipse等IDE集成,方便在开发环境中进行内存分析和调试。 总之,MAT是一款功能强大的内存分析工具,可以帮助开发人员深入分析和优化Java应用程序的内存使用情况。通过对.hprof文件分析开发人员可以定位和解决内存泄漏、内存占用过高等问题,提升应用程序的性能和稳定性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不愿放下技术的小赵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值