JVM 内存分析工具 Memory Analyzer Tool(MAT)的深度讲解

目录

一. 前言

二. MAT 使用场景及主要解决问题

三. MAT 基础概念

3.1. Heap Dump

3.2. Shallow Heap

3.3. Retained Set

3.4. Retained Heap

3.5. Dominator Tree

3.6. OQL

3.7. references

四. MAT 功能概述

4.1. 内存分布

4.2. 对象间依赖

4.3. 对象状态

4.4. 按条件检索对象

4.5. 常见内存分析工具对比

五. Quick Start 及使用技巧

5.1. Quick Start

5.2. 使用技巧及注意事项


一. 前言

    Memory Analyzer Tool(简称:MAT),是一款快速便捷且功能强大丰富的 JVM 堆内存离线分析工具。其通过展现 JVM 异常时所记录的运行时堆转储快照(Heap Dump)状态(正常运行时也可以做堆转储分析),帮助定位内存泄漏问题或优化大内存消耗逻辑。

二. MAT 使用场景及主要解决问题

场景一:内存溢出,JVM 堆区或方法区放不下存活及待申请的对象。如:高峰期系统出现 OOM(Out of Memory)异常,需定位内存瓶颈点来指导优化。

场景二:内存泄漏,不会再使用的对象无法被垃圾回收器回收。如:系统运行一段时间后出现 Full GC,甚至周期性 OOM 后需人工重启解决。

场景三:内存占用高。如:系统频繁 GC ,需定位影响服务实时性、稳定性、吞吐能力的原因。

三. MAT 基础概念

3.1. Heap Dump

    Heap Dump 是 Java 进程堆内存在一个时间点的快照,支持 HPROF 及 DTFJ 格式,前者由 Oracle 系列 JVM 生成,后者是 IBM 系列 JVM 生成。其内容主要包含以下几类:
1. 所有对象的实例信息:对象所属类名、基础类型和引用类型的属性等。
2. 所有类信息:类加载器、类名、继承关系、静态属性等。
3. GC Root:GC Root 代表通过可达性分析来判定 JVM 对象是否存活的起始集合。JVM 采用追踪式垃圾回收(Tracing GC)模式,从所有 GC Roots 出发通过引用关系可以关联的对象就是存活的(且不可回收),其余的不可达的对象(Unreachable object:如果无法从 GC Root 找到一条引用路径能到达某对象,则该对象为Unreachable object)可以回收。
4. 线程栈及局部变量:快照生成时刻的所有线程的线程栈帧,以及每个线程栈的局部变量。

3.2. Shallow Heap

    Shallow Heap 代表一个对象结构自身所占用的内存大小,不包括其属性引用对象所占的内存。如 java.util.ArrayList 对象的 Shallow Heap 包含8字节的对象头、8字节的对象数组属性 elementData 引用 、 4字节的 size 属性、4字节的 modCount 属性(从 AbstractList 继承及对象头占用内存大小),有的对象可能需要加对齐填充但 ArrayList 自身已对齐不需补充,注意不包含 elementData 具体数据占用的内存大小。

3.3. Retained Set

    一个对象的 Retained Set,指的是该对象被 GC 回收后,所有能被回收的对象集合(如下图所示,G 的 Retain Set 只有 G 并不包含 H,原因是虽然 H 也被 G 引用,但由于 H 也被 F 引用 ,G 被垃圾回收时无法释放 H);另外,当该对象无法被 GC 回收,则其 Retained set 也必然无法被 GC 回收。

3.4. Retained Heap

    Retained Heap 是一个对象被 GC 回收后,可释放的内存大小,等于释放对象的 Retained Heap 中所有对象的 Shallow Heap 的和(如下图所示,E 的 Retain Heap 就是 G 与 E 的 Shallow Heap 总和,同理不包含 H)。

3.5. Dominator Tree

    如果所有指向对象 Y 的路径都经过对象 X,则 X 支配(dominate) Y(如下图中,C、D 均支配 F,但 G 并不支配 H)。Dominator tree 是根据对象引用及支配关系生成的整体树状图,支配树清晰描述了对象间的依赖关系,下图左的 Dominator tree 如下图右下方支配树示意图所示。支配关系还有如下关系:
1. Dominator tree 中任一节点的子树就是被该节点支配的节点集合,也就是其 Retain Set。
2. 如果 X 直接支配 Y,则 X 的所有支配节点均支配 Y。

3.6. OQL

    OQL 是类似于 SQL 的 MAT 专用统一查询语言,可以根据复杂的查询条件对 dump 文件中的类或者对象等数据进行查询筛选。

3.7. references

    outgoing references、incoming references 可以直击对象间依赖关系,MAT 也提供了链式快速操作。
1. outgoing references:对象引用的外部对象(注意不包含对象的基本类型属性。基本属性内容可在 inspector 查看)。
2. incoming references:直接引用了当前对象的对象,每个对象的 incoming references 可能有 0 到多个。

四. MAT 功能概述

    MAT 的产品能力非常丰富,工作原理是对 dump 文件建立多种索引,并基于索引来实现:1. 内存分布;2. 对象间依赖(如实体对象引用关系、线程引用关系、ClassLoader引用关系等);3. 对象状态(内存占用量、字段属性值等);4. 条件检索(OQL、正则匹配查询等)。这四大核心功能,并通过可视化展现辅助 Developer 精细化了解 JVM 堆内存全貌。

4.1. 内存分布

全局概览信息:堆内存大小、对象个数、类的个数、类加载器的个数、GC root 个数、线程概况等全局统计信息。

Dominator tree:按对象的 Retain Heap 排序,也支持按多个维度聚类统计,最常用的功能之一。

Histogram:罗列每个类实例的内存占比,包括自身内存占用量(Shallow Heap)及支配对象的内存占用量(Retain Heap),支持按 package、class loader、super class、class 聚类统计,最常用的功能之一。

Leak Suspects:直击引用链条上占用内存较多的可疑对象,可解决一些基础问题,但复杂的问题往往帮助有限。

Top Consumers:展现哪些类、哪些 class loader、哪些 package 占用最高比例的内存。

4.2. 对象间依赖

References:提供对象的外部引用关系、被引用关系。通过任一对象的直接引用及间接引用详情(主要是属性值及内存占用),进而提供完善的依赖链路详情。

Dominator tree:支持按对象的 Retain Heap 排序,并提供详细的支配关系,结合 references 可以实现大对象快速关联分析。

Thread overview:展现转储 dump 文件时线程栈帧等详细状态,也提供各线程的 Retain Heap 等关联内存信息。

Path To GC Roots:提供任一对象到 GC Root 的链路详情,帮助了解不能被 GC 回收的原因。

4.3. 对象状态

最核心的是通过 inspector 面板提供对象的属性信息、类继承关系信息等数据,协助分析内存占用高与业务逻辑的关系。

集合状态的检测,如:通过 ArrayList 或数组的填充率定位空集合空数组造成的内存浪费、通过 HashMap 冲突率判定 hash 策略是否合理等。

4.4. 按条件检索对象

OQL:提供一种类似于SQL的对象(类)级别统一结构化查询语言。如:查找 size=0 且未使用过的 ArrayList: select * from java.util.ArrayList where size=0 and modCount=0;查找所有的String的 length 属性的: select s.length from instanceof String s。

内存分布及对象间依赖的众多功能,均支持按字符串检索、按正则检索等操作。

按虚拟内存地址寻址,根据对象的十六进制地址查找对象。

此外,为了便于记忆与回顾,整理了如下脑图:

4.5. 常见内存分析工具对比

下图中 Y 表示支持,N 表示不支持,时间截至发稿前。

产品功能MATJProfilerVisual VMjhatjmaphprof
对象关联分析、深浅堆、GC ROOT、内存泄漏检测、线程分析、提供自定义程序扩展扩展YNNNNN
离线全局分析YNYYNN
内存实时分配情况NYYYYY
OQLYNYNNN
内存分配堆栈、热点比例NYNNNN
堆外内存分析NNNNNN

注 1:Dump 文件包含快照被转储时刻的 Java 对象在堆内存中的分布情况,但快照只是瞬间的记录,所以不包含对象在何时、在哪个方法中被分配这类信息。

注 2:一般堆外内存溢出排查可结合 gperftools 与 btrace 排查,本文不展开介绍。

五. Quick Start 及使用技巧

5.1. Quick Start

1. 安装 MAT:【下载链接】;也可直接集成到 Eclipse IDE中(路径:Eclipse → Help → Eclipse Marketplace → 搜 “MAT”)。

2. 调节 MAT 堆内存大小:MAT 分析时也作为 Java 进程运行,如果有足够的内存,建议至少分配 dump 文件大小 * 1.2 倍的内存给 MAT,这样分析速度会比较快。方式是修改 MemoryAnalyer.ini文件,调整 Xmx 参数(Windows 可用搜索神器 everything 软件查找并修改、MAC OS 一般在 /Applications/mat.app/Contents/Eclipse/MemoryAnalyzer.ini,如找不到可用 Alfred 软件查询修改)。

3. 获取堆快照 dump 文件(堆转储需要先执行 Full GC,线上服务使用时请注意影响),一般用三种方式:
1>. 使用 JDK 提供的 jmap 工具,命令是 jmap -dump:format=b,file=文件名 进程号。当进程接近僵死时,可以添加 -F 参数强制转储:jmap -F -dump:format=b,file=文件名 进程号。
2>. 本地运行的 Java 进程,直接在 MAT 使用 File → accquire heap dump 功能获取。
3>. 启动 Java 进程时配置JVM参数:-XX:-HeapDumpOnOutOfMemoryError,当发生 OOM 时无需人工干预会自动生成 dump文件。指定目录用 -XX:HeapDumpPath=文件路径来设置。

4. 分析 dump 文件:路径是 File → Open Heap Dump ,然后 MAT 会建立索引并分析,dump 文件较大时耗时会很长。分析后 dump 文件所在目录会有后缀为 index 的索引文件,也会有包含 HTML 格式的后缀为 zip 的文件。

5. 完成索引计算后,MAT 呈现概要视图(Overview),包含三个部分:
1>. 全局概览信息,堆内存大小、类数量、实例数量、Class Loader数量。
2>. Unreachable Object Histogram,展现转储快照时可被回收的对象信息(一般不需要关注,除非 GC 频繁影响实时性的场景分析才用到)。
3>. Biggest Objects by Retained Size,展现经过统计过的哪几个实例所关联的对象占内存总和较高,以及具体占用的内存大小,一般相关代码比较简单情况下,往往可以直接分析具体的引用关系异常,如内存泄漏等。此外也包含了最大对象和链接支持继续深入分析。

6. 如果代码比较复杂,需要继续使用 MAT 各种工具并结合业务代码进一步分析内存异常的原因。最常用的几项如下: 
1>. 查看堆整体情况的:Histogram、Dominator tree、Thread details等(各功能入口整理如下)

2>. MAT 分析过的 Top Consumers 、Leak Suspects 等

5.2. 使用技巧及注意事项

1. 注意对运行进程的性能影响:Heap Dump 时会先进行 Full GC,另外为保证对象数据视图一致,需要在安全点 Stop The World 暂停响应,线上服务进行务必注意性能影响。可以采取以下技巧减少影响:
1>. 先禁用入口流量,再执行 dump 动作。
2>. 选择影响较小时 dump 内存。
3>. 使用脚本捕获指定事件时 dump 内存。

2. Dump 文件及建立的索引文件可能较大,如果开发机配置不足无法分析,可在服务器先执行分析后,基于分析后的索引文件直接查看结果,另外也需要注意磁盘占用问题:
1>. 大文件分析方法:一般 dump 文件不高于分析机主存 1.2 倍可直接在开发机分析;若 dump 文件过大,可以使用 MAT 提供的脚本在配置高的高配机器先建立索引再直接展现索引分析结果(一般是 Linux 机器,可以使用 MAT 提供的脚本:./ParseHeapDump.sh $HEAPDUMP,堆信息有 unreachable 标记的垃圾对象,在 dump 时也保存了下来,默认不分析此部分数据,如需要在启动脚本 ParseHeapDump.sh 中加入:-keep_unreachable_objects)。
2>. 如果不关注堆中不可达对象,使用“live”参数可以减小文件大小,命令是 jmap -dump:live,format=b,file=
3>. Dump 前主动手动执行一次 FULL GC ,去除无效对象进一步减少 dump 堆转储及建立索引的时间。
4>. Dump文件巨大,建立索引后发现主视图中对象占用内存均较小,这是因为绝大部分对象未被 GC Roots 引用可释放。
5>. Dump 时注意指定到空间较大的磁盘位置,避免打满分区影响服务。
6>. 建立 dump 索引机器的磁盘空间需要足够大,一般至少是 dump 文件的两倍,因为生成的中间索引文件也较大,如下图:

3. 其他

1>. JDK 版本问题:如遇“VMVersionMismatchException”,使用启动目标进程的 JDK 版本即可。
2>. 部分核心功能主界面未展现,问题足够复杂时需打开,如 MAT 默认不打开 inspector,如需根据对象数据值做业务分析,建议打开该视图。
3>. 配置了 HeapDumpOnOutOfMemoryError 参数,但 OutOfMemoryError 时但没有自动生成 dump 文件,可能原因有三个:
    3.1>. 应用程序自行创建并抛出 OutOfMemoryError;
    3.2>. 进程的其他资源(如线程)已用尽;
    3.3>. C 代码(如 JVM 源码)中堆耗尽,这种可能由于不同的原因而出现,例如在交换空间不足的情况下,进程限制用尽或仅地址空间的限制,此时 dump 文件分析并无实质性帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/233242.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

docker容器配置MySQL与远程连接设置(纯步骤)

以下为ubuntu20.04环境,默认已安装docker,没安装的网上随便找个教程就好了 拉去mysql镜像 docker pull mysql这样是默认拉取最新的版本latest 这样是指定版本拉取 docker pull mysql:5.7查看已安装的mysql镜像 docker images通过镜像生成容器 docke…

Git的安装以及SSH配置

前言 近期工作需要,所以版本管理工具要用到Git,某些操作需要ssh进行操作,在某次操作中遇到:git bash报错:Permission denied, please try again。经排查是ssh没有配置我的key,所以就借着这篇文章整理了一下…

典型的ETL使用场景

典型的ETL使用场景 ETL( Extract,Transform,Load)是一种用于数据集成和数据转换的常用技术。它主要用于从多个数据源中提取数据,对数据进行清洗、转换和整合,最后加载到目标系统中。ETL 的使用场景非常广泛,下面将介绍…

Windows系统Java开发环境安装

总结一下Java软件开发工程师常见的环境的安装,仅限Windows环境。 以下下载链接均来自官网,网络条件自己克服。 目录 1. JDKJDK Oracle 官网下载地址配置系统环境变量 2. Mavenapache maven 官网地址本地仓库和中央仓库配置配置系统环境变量 3. GitGit 官…

【Docker一】Docker架构、镜像操作和容器操作

一、docker基本管理和概念 1、概念 docker:开源的应用容器引擎。基于go语言开发的。运行在Linux系统中的开源的轻量级的“虚拟机” docker的容器技术可用在一台主机上轻松到达为任何应用创建一个轻量级到的,可移植的,自给自足的容器 dock…

二维码智慧门牌管理系统:提升管理效率

文章目录 前言一、快速准确录入:提高工作效率二、多样化支付:提供高效支付功能三、智能化管理:提高效率与准确性 前言 科技时代的必备工具 在当今科技高速发展的时代,二维码智慧门牌管理系统已成为各行业提高管理效率和准确性的重…

智能仪表板DevExpress Dashboard v23.1 - 支持自定义样式创建

使用DevExpress Analytics Dashboard,再选择合适的UI元素(图表、数据透视表、数据卡、计量器、地图和网格),删除相应参数、值和序列的数据字段,就可以轻松地为执行主管和商业用户创建有洞察力、信息丰富的、跨平台和设…

C语言——字符函数和字符串函数(一)

📝前言: 这篇文章对我最近学习的有关字符串的函数做一个总结和整理,主要讲解字符函数和字符串函数(strlen,strcpy和strncpy,strcat和strncat)的使用方法,使用场景和一些注意事项&…

gin投票项目5

对应视频V3版本 1.优化用户注册的功能 增加扩展字段 1.增加一个UUID字段,vachar(50)。 2.增加一个UUID的唯一索引。 UUID具有全局唯一性; 方法:在数据库中新建一个列,名为uuid并移至主键下方&#xf…

CRM系统选择技巧,什么样的CRM系统好用?

SaaS行业发展迅速,更多的企业逐渐选择CRM管理系统。打开搜索引擎,有非常多的结果。怎样在数十万个搜索结果中选择适合您的CRM系统?下面我们将聊聊,怎样选择CRM系统。 第一步:明确自身需求 重要性:每家企业…

POJ1182 食物链(并查集)

题目展示 Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形。A吃B, B吃C,C吃A。 现有N个动物,以1-N编号。每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种。 有人用…

【Linux】探索Linux进程状态 | 僵尸进程 | 孤儿进程

最近,我发现了一个超级强大的人工智能学习网站。它以通俗易懂的方式呈现复杂的概念,而且内容风趣幽默。我觉得它对大家可能会有所帮助,所以我在此分享。点击这里跳转到网站。 目录 一、进程状态1.1运行状态1.2阻塞状态1.3挂起状态 二、具体L…

在UE中使用Python设置枚举类属性值的问题

目标 在UE编辑器中使用Python设置枚举类属性值会遇到些问题,本篇记录了这些问题的解决方法。 1. 设置数值类属性值 先在编辑器中选择一个Actor,然后运行下面Python代码: actor unreal.EditorLevelLibrary.get_selected_level_actors()[0…

【JavaEE】线程池

作者主页:paper jie_博客 本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。 本文于《JavaEE》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精力)打造&…

2024年网络安全竞赛-Web安全应用

Web安全应用 (一)拓扑图 任务环境说明: 1.获取PHP的版本号作为Flag值提交;(例如:5.2.14) 2.获取MySQL数据库的版本号作为Flag值提交;(例如:5.0.22) 3.获取系统的内核版本号作为Flag值提交;(例如:2.6.18) 4.获取网站后台管理员admin用户的密码作为Flag值提交…

我的隐私计算学习——隐私集合求交(1)

笔记内容来自多本书籍、学术资料、白皮书及ChatGPT等工具,经由自己阅读后整理而成。 (一)PSI的介绍 隐私计算关键技术:隐私集合求交(PSI)原理介绍 隐私计算关键技术:隐私集合求交&#xff08…

【基于Flask、MySQL和Echarts的热门游戏数据可视化平台设计与实现】

基于Flask、MySQL和Echarts的热门游戏数据可视化平台设计与实现 前言数据获取与清洗数据集数据获取数据清洗 数据分析与可视化数据分析功能可视化功能 创新点结语 前言 随着游戏产业的蓬勃发展,了解游戏销售数据对于游戏从业者和游戏爱好者都至关重要。为了更好地分…

【Python数据结构与算法】—— 搜索算法 | 期末复习不挂科系列

​ 🌈个人主页: Aileen_0v0🔥系列专栏: 数据结构与算法💫个人格言:"没有罗马,那就自己创造罗马~" 这篇博客主要探索的是计算机科学常见问题---搜索算法 “时间紧,任务重!” 话不多说,开始今天…

高工氢电年会 | 未势能源解超朋博士受邀出席并做主题演讲

12月4日,以“战略重构 商业觉醒”为主题的2023高工氢电年会在深圳举办,未势能源副总裁解超朋博士受邀出席开幕式论坛,以《把握机遇、直面挑战,迎接氢车规模化推广时代》为主题发表演讲,并参与圆桌论坛研讨。 氢势已来&…

Linux系统中进程的背景(只从数据层面和硬件层面分析)

目录 1、冯诺依曼体系 2、管理的本质 3、 操作系统是如何对硬件进行管理的 4、 计算机的软硬件结构 5、 进程的组成 1、冯诺依曼体系 冯诺依曼是很早就提出的一个体系结构,他是将计算机分成五个部分,输入设备、输出设备、存储器、运算器和控制器。其中运…
最新文章