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

news2024/12/17 17:29:51

目录

一. 前言

二. 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.coloradmin.cn/o/1299121.html

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

相关文章

【交流】PHP生成唯一邀请码

目录 前言: 1.随机生成,核对user表是否已存在 代码: 解析: 缺点: 2.建表建库,每次从表中随机抽取一条,用完时扩充 表结构 表视图 代码 解析 缺点 结论: 前言: …

【rabbitMQ】rabbitMQ的下载,安装与配置

目录 1. 下载Erland 安装步骤: 配置环境变量: 校验环境变量配置是否成功 2.下载MQ 安装步骤: 添加可视化插件 : 启动: 拒绝访问 1. 下载Erland 因为rabbitMQ是基于Erland,所以在安装rabbitMQ之前需要安装Erla…

距离度量(各距离含义)

欧氏距离 在n维空间中两点的真实距离,向量的自然长度 由于欧几里得几何学的关系称为欧氏距离 二维空间两点计算公式: d ( x 1 − x 2 ) 2 ( y 1 − y 2 ) 2 d \sqrt{(x_1 - x_2)^2 (y_1 - y_2)^2} d(x1​−x2​)2(y1​−y2​)2 ​ 三维空间两点计算…

7.MySQL 存储过程

目录 概述 概念: 特性: 变量 局部变量 定义方法: 语法1: 语法2: 用户变量 语法: 系统变量 全局变量 会话变量 参数传递 in out inout 流程控制 分支语句 if case 循环语句 循环控制: while while while…

Java面试遇到的一些常见题

目录 1. Java语言有几种基本类型,分别是什么? 整数类型(Integer Types): 浮点类型(Floating-Point Types): 字符类型(Character Type): 布尔类…

基于Springboot的校园失物招领系统(有报告)。Javaee项目,springboot项目。

演示视频: 基于Springboot的校园失物招领系统(有报告)。Javaee项目,springboot项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结构…

【智能家居】七、人脸识别 翔云平台编程使用(编译openSSL支持libcurl的https访问、安装SSL依赖库openSSL)

一、翔云 人工智能开放平台 API文档开发示例下载 二、编译openSSL支持libcurl的https访问 安装SSL依赖库openSSL(使用工具wget)libcurl库重新配置,编译,安装运行(运行需添加动态库为环境变量) 三、编程实现人脸识别 四、Base6…

react中使用react-konva实现画板框选内容

文章目录 一、前言1.1、API文档1.2、Github仓库 二、图形2.1、拖拽draggable2.2、图片Image2.3、变形Transformer 三、实现3.1、依赖3.2、源码3.2.1、KonvaContainer组件3.2.2、use-key-press文件 3.3、效果图 四、最后 一、前言 本文用到的react-konva是基于react封装的图形绘…

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

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

深度学习之全面了解预训练模型

在本专栏中,我们将讨论预训练模型。有很多模型可供选择,因此也有很多考虑事项。 这次的专栏与以往稍有不同。我要回答的问题全部源于 MathWorks 社区论坛(ww2.mathworks.cn/matlabcentral/)的问题。我会首先总结 MATLAB Answers …

计算机视觉-05-目标检测:LeNet的PyTorch复现(MNIST手写数据集篇)(包含数据和代码)

文章目录 0. 数据下载1. 背景描述2. 预测目的3. 数据总览4. 数据预处理4.1 下载并加载数据,并做出一定的预先处理4.2 搭建 LeNet-5 神经网络结构,并定义前向传播的过程4.3 将定义好的网络结构搭载到 GPU/CPU,并定义优化器4.4 定义训练过程4.5…

机器学习算法(9)——集成技术(Bagging——随机森林分类器和回归)

一、说明 在这篇文章,我将向您解释集成技术和著名的集成技术之一,它属于装袋技术,称为随机森林分类器和回归。 集成技术是机器学习技术,它结合多个基本模块和模型来创建最佳预测模型。为了更好地理解这个定义,我们需要…

C语言进阶之路之结构体、枚举关卡篇

目录 一、学习目标 二、组合数据类型-结构体 结构体基本概念 结构体的声明: 小怪实战 结构体初始化 指定成员初始化的好处: 结构体成员引用 结构体指针与数组 关卡BOOS 三、结构体的尺寸 CPU字长 地址对齐 结构体的M值 可移植性 四、联合体…

ssm的健身房预约系统(有报告)。Javaee项目。ssm项目。

演示视频: ssm的健身房预约系统(有报告)。Javaee项目。ssm项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结构,通过Spring Spring…

极智一周 | AI 算力国产化、通义开源、Gemini、鸿蒙、蔚来 And so on

欢迎关注我的公众号 [极智视界],获取我的更多技术分享 大家好,我是极智视界,带来本周的 [极智一周],关键词:AI 算力国产化、通义开源、Gemini、鸿蒙、蔚来 And so on。 邀您加入我的知识星球「极智视界」,…

c-语言->数据在内存的存储

系列文章目录 文章目录 系列文章目录前言 前言 目的:学习整数在内存的储存,什么是大小端,浮点数的储存。 1. 整数在内存中的存储 在讲解操作符的时候,我们就讲过了下⾯的内容: 整数的2进制表⽰⽅法有三种&#xff0…

带有 RaspiCam 的 Raspberry Pi 监控和延时摄影摄像机

一、说明 一段时间以来,我一直想构建一个运动激活且具有延时功能的树莓派相机,但从未真正找到我喜欢的案例。我在thingiverse上找到了这个适合树莓派和相机的好案例。它是为特定的鱼眼相机设计的,但从模型来看,我拥有的廉价中国鱼…

STM32F1之CAN报文传输

目录 报文传输 1. 帧类型 1.1 数据帧 1.1.1 帧起始 1.1.2 仲裁场 1.1.3 控制场 1.1.4 数据场 1.1.5 CRC 场 1.1.6 应答场 1.1.7 帧结尾 1.2 远程帧 1.3 错误帧 1.4 过载帧 1.5 帧间空间(INTERFRAME SPACING) 2. 发送器/接收器的…

【动态规划】【广度优先】LeetCode2258:逃离火灾

作者推荐 本文涉及的基础知识点 二分查找算法合集 动态规划 二分查找 题目 给你一个下标从 0 开始大小为 m x n 的二维整数数组 grid ,它表示一个网格图。每个格子为下面 3 个值之一: 0 表示草地。 1 表示着火的格子。 2 表示一座墙,你跟…

【C语言】内联函数

一、内联函数 在C语言中,内联函数(Inline function)是一种代码优化技术,它的目的是减少函数调用的开销。内联函数通知编译器在每个函数调用的位置插入函数的实际代码,而不是进行传统的函数调用。这避免了调用函数时的…