使用MAT分析线上问题实战
创始人
2024-03-06 10:34:13
0

概述

MAT,下载地址,Eclipse Memory Analysis Tools,一个分析Java堆数据的专业工具,可以计算出内存中对象的实例数量、占用空间大小、引用关系等,可得知哪些线程阻止垃圾收集器的回收工作,从而定位内存泄漏的原因。

什么时候会用到MAT?

  1. OutOfMemoryError时,触发Full GC,但空间却回收不了,引发内存泄露
  2. Java服务器系统异常,如load飙高,io异常,或线程死锁等,都可能通过分析堆中的内存对象来定位原因

分析堆转储文件需要消耗很多的堆空间,为保证分析的效率和性能,建议给MAT分配尽可能多的内存资源。两种方式:

  1. 修改启动参数MemoryAnalyzer.exe -vmargs -Xmx4g
  2. 编辑文件MemoryAnalyzer.ini添加-vmargs – Xmx4g

生成堆转储文件

简单来说使用jmap -dump命令可以生成堆转储文件。首先需要执行进程ID,即PID。通过topjps命令拿到Java进程pid

具体执行命令:jmap -dump:format=b,file=heap.hprof

如果执行命令报错:

Unable to open socket file: target process not responding or HotSpot VM not loaded.The -F option can be used when the target process is not responding

则执行命令:jmap -F -dump:format=b,file=heap.hprof
命令执行时,JVM会将整个heap的信息dump写入到一个文件,heap如果比较大的话,就会导致这个过程比较耗时,且执行过程中为保证dump的信息是可靠的,会暂停应用。

可通过-d64来解决:jmap -F -J -d64 -dump:format=b,file=dump.bin PID

一般dump下来的文件有几个G,如果dump下来的文件只有一两百M,说明jmap命令执行有问题,需多执行几次才能得出正常结果,这个时候可以选用gcore把整个内存dump出来,然后再使用jmap把core dump转换成heap dump。

做法就是用gcore 1234命令来生成c版的core文件,再用命令jmap -dump:format=b,file=heap.hprof /bin/java core.1234.

概念

Shallow Size

Shallow size就是对象本身占用内存的大小,不包含其引用的对象。常规对象(非数组)的 Shallow size 由其成员变量的数量和类型决定。数组的 shallow size 由数组元素的类型(对象类型、基本类型)和数组长度决定。

在 32 位系统上,对象头占用 8 字节。int 占用 4 字节,不管成员变量(对象或数组)是否引用其他对象(实例)或赋值为 null 它始终占用 4 字节。对于 String 对象实例来说,它有三个 int 成员(34=12 字节)、一个 char[] 成员(14=4 字节)以及一个对象头(8 字节),总共 34 +14+8=24 字节。

注意JDK 版本区别:

public final class String implements java.io.Serializable, Comparable, CharSequence {/** The value is used for character storage. */private final char value[];/** The offset is the first index of the storage that is used. */private final int offset;/** The count is the number of characters in the String. */private final int count;/** Cache the hash code for the string */private int hash; // Default to 0
}

Retained Size

对象的 Retained Size = 对象本身的 Shallow Size + 对象能直接或间接访问到对象的 Shallow Size。即,Retained Size 就是该对象被 Gc 之后所能回收内存的总和。即,该对象到其他对象有引用关系并且该引用对象到 Gc Root 节点是不可达的。总之,Retained size 是一个整体度量,能反映内存结构和对象图的依赖关系,还可以找到根节点。在进行GC时,如果实例对象到 Gc Root 是不可达的,那么该对象会被回收。

Heap Size

堆的大小,当资源增加,当前堆的空间不够时,系统会增加堆的大小,若超过上限(如 64M,阈值视平台而定)则会被杀掉 。

Allocated

堆中已分配的大小,即 App 应用实际占用的内存大小,资源回收后,此项数据会变小。

建议:若单一操作反复进行,堆大小一直增加,则有内存泄露的隐患,可采用 MAT 进一步查看。

问题

Java heap space

打开dump1.phrof文件失败,报错信息如下:
在这里插入图片描述
解决方案:
编辑MemoryAnalyzer.ini文件,修改-Xmx1024m-Xmx2048m,当然也可以修改为其他数值,大于1024即可,然后得是2的n次方。参考链接见文末。

The HPROF parser encountered a violation

打开dump1.phrof文件失败,报错信息如下:
在这里插入图片描述
详细的报错日志:

The HPROF parser encountered a violation of the HPROF specification that it could not safely handle. This could be due to file truncation or a bug in the JVM. Please consider filing a bug at eclipse.org. To continue parsing the dump anyway, you can use -DhprofStrictnessWarning=true or set the strictness mode under Preferences > HPROF Parser > Parser Strictness. See the inner exception for details.
The HPROF parser encountered a violation of the HPROF specification that it could not safely handle. This could be due to file truncation or a bug in the JVM. Please consider filing a bug at eclipse.org. To continue parsing the dump anyway, you can use -DhprofStrictnessWarning=true or set the strictness mode under Preferences > HPROF Parser > Parser Strictness. See the inner exception for details.
(Possibly) Invalid HPROF file: Expected to read another 3,458,508,632 bytes, but only 125,883,023 bytes are available for heap dump record 0x21 at 0x8114f34a.
(Possibly) Invalid HPROF file: Expected to read another 3,458,508,632 bytes, but only 125,883,023 bytes are available for heap dump record 0x21 at 0x8114f34a.

解决方案:
考虑到上面的问题1,没有Google搜索,直接在配置文件MemoryAnalyzer.ini里面增加一行配置:-DhprofStrictnessWarning=true,重启MAT,重新打开dump1.phrof文件,解析成功。

实战

打开一个.hprof文件,主要有三个模块,左侧顶部的Inspector,左侧底部如下信息:
在这里插入图片描述
右侧主面板:
在这里插入图片描述

  • 工具栏及Overview
  • Details:概要信息,如空间大小、类的数量、对象实例数量、类加载器等
  • Biggest Objects by Retained Size:以饼状图给出大对象,鼠标移动到饼图某个区域上方,在左侧会看到对象的详细信息
  • Atcion提供多种分析维度:
    • Histogram:按类列出内存中的对象,对象的个数以及大小
    • Dominator Tree:支配树,分析对象的引用关系
    • Top Consumers:
    • Duplicate Classes:
  • Reports:
    • Leak Suspects:分析内存泄漏
    • Top Components:
  • Step By Step:

概念:
Shallow Heap:类对象本身占用内存大小,不包含其引用的对象内存
Retained Heap:对象自己占用内存 + 关联引用对象占用大小。相对于shallow heap,RetainedHeap可以更精确的反映一个对象实际占用的大小(因为如果该对象释放,retained heap都可以被释放)。
Retained Set:指这个对象本身和他持有引用的对象以及这些引用对象的Retained Set所占内存大小的总和

Histogram

该视图以Class类的维度展示每个Class类的实例存在的个数、占用的[Shallow内存]和[Retained内存]大小,可分别降序显示(升序没有意义),尤其是对Retained内存降序展示,

还可以按照对象或Class引用和被引用展示:List objects or Show objects by class:

  • with incoming references:列出哪些类引入该类
  • with outgoing references:出该类引用哪些类

多数情况下,在Histogram视图看到实例对象数量比较多的类都是一些基础类型,如char[](因为其构成String)、String、byte[],所以仅从这些是无法判断出具体导致内存泄露的类或者方法的,可以使用 List objects 或 Merge Shortest Paths to GC roots–>exclude all phantom/weak/soft etc.reference(排除所有虚弱软引用)–>查看剩余未被回收的强引用对象占用原因 等功能继续钻取数据。如果Histogram视图展示的数量多的实例对象不是基础类型,是有嫌疑的某个类,如项目代码中的bean类型,那么就要重点关注了。

打开方式:

  1. Overview > Actions > The Histogram
  2. 工具栏 > Histogram

Dominator Tree

支配树,分析对象的引用关系。 对象内存占用&占比

dominate_tree -> 对象调用堆栈树-查找内存占用最高对象(Retained Heap倒叙排序) -> Paths to GC Roots -> exclude all phantom/weak/soft etc.reference(排除所有虚弱软引用) -查找GC Root线程-> 定位未释放内存代码段

Actions > dominator_tree (查看堆中内存占用最高的对象的线程调用堆栈) -> 对象调用堆栈树-查找内存占用最高对象(Retained Heap倒叙排序) -> Paths to GC Roots -> exclude all phantom/weak/soft etc.reference (排除所有虚弱软引用) -查找GC Root线程 -> 查找未释放的内存占用最高的代码逻辑段(很可能是产生内存溢出代码)

Leak Suspects

打开方式:

  1. Overview > Reports > Leak Suspects
  2. 工具栏 > Run Expect System Test > Leak Suspects

自动分析内存泄露可疑点,给出一份可疑分析报告。MAT将报告内容压缩打包到一个zip文件,并放在原始堆转储文件的目录下,一般命名为xxx_Leak_Suspects.zip,xxx是dump文件名,zip包文件很小,方便分发共享,请教他人协助排查内存泄露问题;报告是HTML文件。

以饼状图给出可疑的内存泄漏点,Details明细

OQL

Object Query Language,类似于SQL,能够用来查询当前内存中满足指定条件的所有对象。

Thread Overview

可看到:线程对象/线程栈信息、线程名、Shallow Heap、Retained Heap、类加载器、是否Daemon线程等信息。结合左侧的对象属性区域,可以更方便的看清线程中对象的具体情况。

打开方式:工具栏

Query Browser

对比dump堆栈文件

复杂的内存泄漏情况,需要通过对比hpof文件来进行分析。
生成第一个hpof文件,进行一段时间操作,再生成第二个hpof文件。用MAT打开这两个hpof文件。
将第一个和第二个hpof文件的Dominator Tree或者Histogram添加到Compare Basket中,之后选中2个文件对比即可
2个dump文件对比寻找波动差异(关注差异波动大的对象)

参考

  • MAT open heap dump file failed with java heap space
  • Eclipse Memory Analyzer Tool Help
  • 使用MAT分析线上故障(一) - 视图&功能篇

相关内容

热门资讯

三部门:不断完善学前教育成本分... 观点网讯:12月23日,国家发展改革委、教育部、财政部联合发布《关于完善幼儿园收费政策的通知》,要求...
汪清林区法院:化解未成年人纠纷... 近日,吉林省汪清林区法院审结了一起涉未成年人在校遭受人身损害案件,法院充分考量了未成年人的行为特点及...
北京市长城保护条例 北京市人民代表大会常务委员会公告 〔十六届〕第45号 《北京市长城保护条例》已由北京市第十六届人民代...
棒杰股份(002634)披露关... 截至2025年12月23日收盘,棒杰股份(002634)报收于5.28元,较前一交易日下跌4.52%...
高盛再度唱多!预计中国股市到2... 来源:视觉中国 界面新闻编辑 | 江怡曼 近日,高盛发布名为《中国策略:2025年中国股市十大...
尤文身价变化:共10人身价下降... 在意甲联赛的激烈竞争中,尤文图斯的球员身价变化引发了广泛关注。根据最新的德转数据,尤文队内有10名球...
美国发布H-1B签证新规,优先... 当地时间12月23日,美国国土安全部发布新规,正式以“加权选择”机制取代H-1B签证原有的随机抽签制...
悉尼恐袭事件,意外替德国默茨政... 刚刚过去的一周,发生在澳大利亚的悉尼邦迪海滩恐怖袭击事件引起全球关注。 对于万里之外的德国而言,这场...
视频丨“粤车南下”驶入香港市区... 今天(12月23日),“粤车南下”驶入香港市区政策正式实施,符合条件的广东私家车可直接驶入香港市区,...
立白回应与经销商解约纠纷:个别... 12月23日,红星新闻报道《多地代理商称与立白集团解约后 对方未按约交接市场致严重损失,律师解读》一...