当前位置:网站首页 > R语言数据分析 > 正文

hprof文件怎么分析 mat(hprof文件怎么分析)



MAT 工具是基于 Eclipse 平台开发的, 本身是一个 Java 程序, 是一款很好的内存分析工具, 所以如果堆快照比较大的话, 则需要一台内存比较大的分析机器, 并给 MAT 本身加大初始内存, 这个可以修改安装目录中的 MemoryAnalyzer.ini 文件。

jemalloc内存分析工具_jemalloc内存分析工具

在MAT中,我们一般比较常用的几个小工具,如下图标识所示

jemalloc内存分析工具_垃圾回收_02

jemalloc内存分析工具_内存泄漏_03

柱状图中,主要看每个class对应的实例数、浅堆、深堆等。如下图所示

jemalloc内存分析工具_jemalloc内存分析工具_04

从这个图的展示效果看出,和“jmap -histo <pid> ”命令展示的效果很像。

而我们大部分情况下,我们关注重点,是深堆或浅堆的incoming和outgoing两项,那么这两项指的是什么呢?

1、对象的引入(incoming references)

通俗的来讲,就是哪些对象把当前对象引用了,那么那些对象对于当前对象来说就是一些引入对象。

2、对象的引出(outgoing references)

通俗的来讲,就是当前对象中引用了哪些对象,那么那些对象对于当前对象来说就是一些引出对象。

下面就使用例子进行说明,准备如下代码

那么这一段码的意图,可以翻译为下面的图所示

jemalloc内存分析工具_jvm_05

下面我们就来分析对象C的Incoming和outgoing

将代码使用main方法运行起来,然后使用MAT连接。

注意MAT不单单只打开 dump 日志,也可以打开正在运行的 JVM 进程, 跟 arthas 有点类似,效果是一样的,只是一个是动态的,一个是日志导出那个时刻的。

使用MAT连接正在运行的进程方式如下图所示

jemalloc内存分析工具_内存泄漏_06

选中如图中标识的这个进程并双出打开

jemalloc内存分析工具_垃圾回收_07

jemalloc内存分析工具_jvm_08

jemalloc内存分析工具_垃圾回收_09

jemalloc内存分析工具_垃圾回收_10

jemalloc内存分析工具_java_11

jemalloc内存分析工具_jvm_12

这个 outgoing references 和 incoming references 非常有用, 因为我们做 MAT 分析一般时对代码不了解, 排查内存泄漏也好, 排查问题也好, 垃圾回收中有一个很重要的概念, 可达性分析算法, 那么根据这个引入和引出, 我就可以知道这些对象的引用关系, 在 MAT 中我们就可以知道比如 A,B,C,D,E,F 之间的引用关系图, 便于做具体问题的分析。

1、概念

  浅堆(shallow heap) 代表了对象本身的内存占用, 包括对象自身的内存占用, 以及“为了引用” 其他对象所占用的内存。

  深堆(Retained heap) 是一个统计结果, 会循环计算引用的具体对象所占用的内存。 但是深堆和“对象大小” 有一点不同, 深堆指的是一个对象被垃圾回收后, 能够释放的内存大小, 这些被释放的对象集合, 叫做保留集(Retained Set)

2、浅堆大小的计算

我们知道,一个对象的大小是由三个部分组成,即对象头、实例数据、对齐填充。

而我们在实际使用中,一个对象会引用其它的对象或一些基本的成员变量。那么这个浅堆大小的计算公式如下

其中,各成员变量大小之和就是实例数据,如果存在继承的情况,需要包括父类成员的变量。

除了对象,我们还需要知道数组类型对象的浅堆该如计算。计算体公式如下

这里的类型变量大小*数组长度, 就是实例数据, 强调是变量不是对象本身

3、实例辨析

下面,给出一张图,我们来看一下,A、B、D这三个对象的深堆和浅堆是怎么得出来的

jemalloc内存分析工具_内存泄漏_13

1、对于A对象而言,浅堆就是自身的大小,即大小为10;深堆的计算可就没有这么简单了,前面说过,对象的深堆是指如果对象被回收了,它所能释放出多少空间,那这么这个释放出来的空间就是深堆大小。从图中,可以看出从A出发,是有6个对象实例,而每个实例的大小是10,但是对象本身的大小是10,所以A的深堆就是70

2、对于B对象而言,按照A对象的计算方式,不能算出,它的浅堆大小是10,而深堆大小是30

3、对于D对象而言,如果D被回收了,它也只释放出的空间大小为10,即它自身的大小。所以它的浅堆和深堆都是10。因此,如果我们在使用MAT工具在分析时,看到浅堆和深堆的大小是一样的话,就可以断定,这个对象就没有引用其它对象了。

下面再看一个图

jemalloc内存分析工具_jemalloc内存分析工具_14

在这种情况下, 对象A的深堆大小将从之前的 70 减小到 40 个字节。如果对象A被垃圾回收了, 则将仅会影响C、 F 和 G 对象的引用,所以仅对象C、F和G 将被垃圾回收。另一方面, 由于H持有对B的引用,对象B、D和E将继续存在于内存中。即使 A 被垃圾回收,B、D和E也不会从内存中删除。

总结:我们可以看到在进行内存分析时,浅堆和深堆是两个非常重要的概念,尤其是深堆,影响着回收这个对象能够带来的垃圾回收的效果,所以在内存分析中,我们往往会去找那些深堆比较的大的对象, 尤其是那些浅堆比较小但深堆比较大的对象, 这些对象极有可能是问题对象。

内存泄露检测

在日常开发中,我们可能会遇到内存泄露问题而不自知,这种问题将会是致命的,如果不找出其中的根原,那么这么始终是一个定时炸弹。那么对于内存泄露这一类的问题,就可以使用MAT工具进行分析。

下面,准备一段简单的代码,如下

我们将这段代码使用main方法运行起来,并使用MAT进行连接

jemalloc内存分析工具_java_15

jemalloc内存分析工具_jvm_16

jemalloc内存分析工具_jemalloc内存分析工具_17

   从上图中,可以看到,存在一个"hl-thread"的线程,它的深堆和浅堆的差距非常的巨大。持有99.53%的对象,数据被一个HashMap所持有。

那么这个就是一个泄露点,因为在代码中对线程做了标识 。所以我们在日常的开发中,如果有用到线程的,最好还是给线程取上名称,这样对排查问题有很大的帮助。

所以, 如果是对于特别明显的内存泄漏, 在这里能够帮助我们迅速定位, 但通常内存泄漏问题会比较隐蔽, 我们需要做更加复杂的分析。

支配树视图

jemalloc内存分析工具_java_18

jemalloc内存分析工具_jemalloc内存分析工具_19

从上图的层层分解得出。原来是“hl-thread”的深堆和浅堆比例很多(深堆比浅堆多很多,一般经验都是找那些浅堆比较小,同时深堆比较大的对象)

经过分析,内存泄露点就在于此。

线程视图

想要看具体的引用关系, 可以通过线程视图。 线程在运行中是可以作为 GC Roots 的。 我们可以通过线程视图展示了线程内对象的引用关系, 以及方法调用关系, 相对比 jstack 获取的栈 dump, 我们能够更加清晰地看到内存中具体的数据。

jemalloc内存分析工具_jemalloc内存分析工具_20

还有另外一段是陷入无限循环,这个是相互引用导致的(进行问题排查不用被这种情况给误导了,这样的情况一般不会有问题,可达性分析算法的解决了相互引用的问题) 。

jemalloc内存分析工具_垃圾回收_21

柱状图视图

柱状图视图,可以看到除了对象的大小, 还有类的实例个数。 结合 MAT 提供的不同显示方式, 往往能够直接定位问题。 也可以通过正则过滤一些信息,我们在这里输入MAT,过滤猜测的、可能出现问题的类, 可以看到, 创建的这些自定义对象, 刚好100个对象实例,而在代码中指定就是100

jemalloc内存分析工具_jemalloc内存分析工具_22

jemalloc内存分析工具_内存泄漏_23

下面我们看一下对象A的引入,即A被哪些对象引用了。

jemalloc内存分析工具_java_24

jemalloc内存分析工具_java_25

Path To GC Roots

jemalloc内存分析工具_jvm_26

jemalloc内存分析工具_java_27

使用这种方式, 即可在引用之间进行跳转, 方便的找到所需要的信息(这里从对象反推到了线程 hl-thread) ,也可以快速定位到有内存泄漏的问题代码。

高级功能QOL

MAT工具支持一种类似于 SQL 的查询语言 OQL(Object Query Language) ,这个查询语言VisualVM工具也支持,不过一般情况下不用VisualVM工具。使用方法如下图

查询A对象

jemalloc内存分析工具_java_28

jemalloc内存分析工具_垃圾回收_29

当然了,QOL用还有更多的用法,可以参考网址 http://tech.novosoft-us.com/products/oql_book.htm

到此这篇hprof文件怎么分析 mat(hprof文件怎么分析)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • cors跨域解决方案(cors跨域问题)2025-02-18 12:36:07
  • yarn命令查看日志(yarn 查看日志)2025-02-18 12:36:07
  • xavier serrano生日(seraphine生日)2025-02-18 12:36:07
  • uchar i(uchar IRKEY_1=0x45可以吗)2025-02-18 12:36:07
  • args怎么读音(arg英语怎么读)2025-02-18 12:36:07
  • 查看Docker版本号的命令为(查找docker版本号的命令)2025-02-18 12:36:07
  • springbootaop日志(springboot aop操作日志)2025-02-18 12:36:07
  • oracle查看锁表进程(oracle 查看锁表进程)2025-02-18 12:36:07
  • pdfview怎么转换成wps(pdfview怎么转换成word)2025-02-18 12:36:07
  • cruise2014安装教程(cruise安装包)2025-02-18 12:36:07
  • 全屏图片