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.mzph.cn/news/212692.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

鸿蒙前端开发-构建第一个ArkTS应用(Stage模型)

创建ArkTS工程 若首次打开DevEco Studio,请点击Create Project创建工程。如果已经打开了一个工程,请在菜单栏选择File > New > Create Project来创建一个新工程。 选择Application应用开发(本文以应用开发为例,Atomic Serv…

docker-compose安装教程

1.确认docker-compose是否安装 docker-compose -v如上图所示表示未安装,需要安装。 如上图所示表示已经安装,不需要再安装,如果觉得版本低想升级,也可以继续安装。 2.离线安装 下载docker-compose安装包,上传到服务…

人工智能原理复习--机器学习

文章目录 上一篇机器学习概述归纳(示例)学习ID3决策树算法K近邻算法下一篇 上一篇 人工智能原理复习–搜索策略(二) 机器学习概述 学习系统的基本结构: #mermaid-svg-JMjIZHjVOirLolvu {font-family:"trebuchet ms",verdana,ari…

辨析旅行商问题(TSP)与车辆路径问题(VRP)

目录 前言旅行商问题 (TSP)问题介绍数学模型符号定义问题输入约束条件目标函数问题输出 解的空间解空间大小计算解释 车辆路径问题 (VRP)问题介绍TSP到VRP的过渡数学模型符号定义问题输入约束条件优化目标问题输出 解空间特殊情况一般情况 TSP 与 VRP 对比 前言 计划是通过本文…

基于JavaWeb+SSM+Vue助农扶贫微信小程序系统的设计和实现

基于JavaWebSSMVue助农扶贫微信小程序系统的设计和实现 源码获取入口Lun文目录前言主要技术系统设计功能截图 源码获取入口 Lun文目录 目 录 第一章 绪论 1 1.1 研究背景 1 1.2 研究意义 1 1.3 研究内容 2 第二章 开发环境与技术 3 2.1 JSP技术 3 2.2 MySQL数据库 3 2.3 Java…

基于Solr的全文检索系统的实现与应用

文章目录 一、概念1、什么是Solr2、与Lucene的比较区别1)Lucene2)Solr 二、Solr的安装与配置1、Solr的下载2、Solr的文件夹结构3、运行环境4、Solr整合tomcat1)Solr Home与SolrCore2)整合步骤 5、Solr管理后台1)Dashbo…

微服务学习:Nacos配置中心

先打开Nacos(详见微服务学习:Nacos微服务架构中的服务注册、服务发现和动态配置&Nacos下载) 1.环境隔离: 新建命名空间: 记住命名空间ID: c82496fb-237f-47f7-91ed-288a53a63324 再配置 就可达成环…

docker-centos中基于keepalived+niginx模拟主从热备完整过程

文章目录 一、环境准备二、主机1、环境搭建1.1 镜像拉取1.2 创建网桥1.3 启动容器1.4 配置镜像源1.5 下载工具包1.6 下载keepalived1.7 下载nginx 2、配置2.1 配置keepalived2.2 配置nginx2.2.1 查看nginx.conf2.2.2 修改index.html 3、启动3.1 启动nginx3.2 启动keepalived 4、…

【HarmonyOS开发】控件开发过程中,知识点记录

1、问题记录及解决方案 1.1 资源(Icon&i18n)问题 控件:只有一个JS文件,不会将任何资源型文件(图片、字体、默认文字等)打包到SO中。因此,当我们开发控件时,需要将需要使用到的资…

【机器学习】042_迁移学习

一、概述、定义 目的: 迁移学习的目的是将某个领域或任务上学习到的模式、知识应用到不同但相关的领域里,获取更多数据,而不必投入许多时间人力来进行数据的标注。 举例: 已经会下中国象棋,就可以类比着来学习国际…

Navicat连接Oracle数据库

Navicat连接Oracle数据库 打开服务里面找到Oracle服务 OracleServerXE或者OracleServerTTL 创建数据库连接 连接名默认自己起 主机选择本地 端口默认 服务名在服务中可以找到输入后缀 用户名默认都是system 密码是创建oracle时候填写的口令 点击测试连接即可

Spring Boot中的事务是如何实现的?懂吗?

SpringBoot中的事务管理,用得好,能确保数据的一致性和完整性;用得不好,可能会给性能带来不小的影响哦。 基本使用 在SpringBoot中,事务的使用非常简洁。首先,得感谢Spring框架提供的Transactional注解&am…

【金融数据分析】计算沪深300指数行业权重分布并用饼图展示

前言 前面的文章我们已经介绍了如何获取沪深300成分股所述行业以及权重的数据,想要了解这部分内容的小伙伴可以阅读上一篇文章 springbootjdbcTemplatesqlite编程示例——以沪深300成分股数据处理为例-CSDN博客 那么有了上文获取的数据,我们实际上可以…

【rabbitMQ】rabbitMQ控制台模拟收发消息

目录 1.新建队列 2.交换机绑定队列 3.查看消息是否到达队列 总结: 1.新建队列 2.交换机绑定队列 点击amq.fonout 3.查看消息是否到达队列 总结: 生产者(publisher)发送消息,先到达交换机,再到队列&…

期末速成数据库极简版【存储过程】(5)

目录 【7】系统存储过程 【8】用户存储过程——带输出参数的存储过程 创建存储过程 存储过程调用 【9】用户存储过程——不带输出参数的存储过程 【7】系统存储过程 系统存储我们就不做过程讲解用户存储过程会考察一道大题,所以我们把重点放在用户存储过程。…

U4_1 语法分析之自顶向下分析

文章目录 一、定义1、任务2、对比3、方法4、自顶向下面临问题 二、自顶向下分析1、概念2、特点3、二义性问题4、左递归问题1)概念2)消除3)间接左递归 5、回溯问题1)概念2)消除3)解决方法 6、总结 三、递归子…

【Proteus仿真】【51单片机】光照强度检测系统

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真51单片机控制器,使共阴数码管,PCF8591 ADC模块、光敏传感器等。 主要功能: 系统运行后,数码管显示光传感器采集光照强度值&#xff…

Gitzip插件【Github免翻下载】

今天给大家推荐一个github下载的插件,平常大家下载应该无外乎就是以下两种: Download zip利用git clone 但是这两种各有各的弊端,前者一般需要科学上网才可以,后者下载不稳定经常中途断掉。 今天给推荐一个款浏览器插件-Gitzip.大…

基于SSM的java衣服商城

基于SSM的java衣服商城 一、系统介绍二、功能展示四、其他系统实现五、获取源码 一、系统介绍 项目类型:Java EE项目 项目名称:基于SSM的美衣商城 项目架构:B/S架构 开发语言:Java语言 前端技术:Layui等 后端技术…

Flask和Vue框架实现WebSocket消息通信

1 安装环境 1.1 安装Flask环境 主要的安装包 Flask、Flask-SocketIO,注意Python版本要求3.6 # Flask-SocketIO参考地址 https://flask-socketio.readthedocs.io/en/latest/ https://github.com/miguelgrinberg/flask-socketio更新基础环境 # 更新pip python -m …