Eclipse Memory Analyzer(MAT)功能介绍

提供的功能

1. overview部分

在这里插入图片描述
38.1MB,就是reachable部分所占的内存大小,包括多少个classes,多少个Objects,以及多少个class loader

2. unreachable objects Histogram

What are unreachable objects in heap dump?

A heap dump can contain unreachable objects, e.g. objects which should be garbage collected but stay around for various reasons. Usually this is due to optimizations in the garbage collection algorithm. The Memory Analyzer removes these objects by default from the object graph.

在这里插入图片描述
因为是unreachable的,所以无法直接查看这些对象的引用

在这里插入图片描述
unreachable objects所占内存为1140M,这个就是很大了,其中java.lang.Object[] + char[],就占了600M


查看objects功能上与visualvm对比

在这一点上jvisualvm很直观,其500个实例为一组,翻一翻就能看到了(jvisualvm中看到的内容应该是 reachable+unreachable)
在这里插入图片描述

jvisualvm中Object[]实例数为627344

在这里插入图片描述
在memory analyzer中

reachable:9355
在这里插入图片描述
unreachable:617989
在这里插入图片描述
这两个之和,正好等于627344


参考:用mat分析内存dump文件中unreachable objects

"然而因为是unreachable的,无法直接查看这些TreeMap对象的引用。如何才有知道到底谁引用它们呢?在代码里grep了一下,发现自己项目中没有任何地方用到TreeMap,从而判断应该是第三方库用到的

注意:下面(从功能3开始)的这些分析都是针对reachable才可以进行的

3. Histogram视图

该视图以Class类的维度展示每个Class类的实例存在的个数、 占用的 [Shallow内存] 和 [Retained内存] 大小,可以分别排序显示。

从Histogram视图可以看出,哪个Class类的对象实例数量比较多,以及占用的内存比较大


Shallow Heap与Retained Heap的区别

Retained Heap(保留大小):仅能通过obj1才能直接或间接访问的对象的shallow heap总和

shallow heap(浅大小):就是其自身的大小

比如这里obj4的shallow Heap,就是obj4的内存大小

obj3的shallow heap,就是obj3的内存大小

obj2的shallow heap,就是obj2的内存大小,而其retained heap,obj2+obj3+obj4
在这里插入图片描述
不过,多数情况下,在Histogram视图看到实例对象数量比较多的类都是一些基础类型,如char[](因为其构成了String)、String、byte[],所以仅从这些是无法判断出具体导致内存泄露的类或者方法的,可以使用 List objectsMerge Shortest Paths to GC roots 等功能继续钻取数据。如果Histogram视图展示的数量多的实例对象不是基础类型,是有嫌疑的某个类,如项目代码中的bean类型,那么就要重点关注了。

4. Dominator Tree视图

该视图以实例对象的维度展示当前堆内存中Retained Heap占用最大的对象,以及依赖这些对象存活的对象的树状结构

视图中展示了实例对象名、Shallow Heap大小、Retained Heap大小、以及当前对象的Retained Heap在整个堆中的占比

点开Dominator Tree实例对象左侧的“+”,会展示出下一层(next level),当所有引用了当前实例对象的引用都被清除后,下一层列出的objects就会被垃圾回收

这也阐明了支配的含义:父节点的回收会导致子节点也被回收,即因为父节点的存在使得子节点存活

Dominator Tree支配树可以很方便的找出占用Retained Heap内存最多的几个对象,并表示出某些objects的是因为哪些objects的原因而存活

5. Group分组功能

在这里插入图片描述
例如在Histogram视图 或 Dominator Tree视图,选择Group by package,可以更好地查看具体是哪个包里的类占用内存大,也很容易定位到自己的应用程序

6. Thread Overview

在Thread Overview视图可以看到:线程对象/线程栈信息、线程名、Shallow Heap、Retained Heap、类加载器、是否Daemon线程等信息

在分析内存Dump的MAT中还可以看到线程栈信息,这本身就是一个强大的功能,类似于jstack命令的效果

当thread dump无法导出,可以通过这种方式查看线程状态,只是这种方式不像文本文件那样直观

而且还能结合内存Dump分析,看到线程栈帧中的本地变量,在左下方的对象属性区域还能看到本地变量的属性,真的很方便

7. List objects

在 Histogram 或 Dominator Tree视图,想要看某个条目(对象/类)的引用关系图,可以使用 List objects 功能

选择 with outgoing references 或 with incoming references

List objects --> with outgoing references

查看当前对象持有的外部对象引用(在对象关系图中为从当前对象指向外的箭头)

List objects --> with incoming references

查看当前对象被哪些外部对象所引用(在对象关系图中为指向当前对象的箭头)

8. Path To GC Roots

在这里插入图片描述
在这里插入图片描述
在查询到GC root的路径时,是包含所有引用,还是排除一些类型的引用(如软引用、弱引用、虚引用),从GC角度说,一个对象无法被GC,一定是因为有强引用存在,其它引用类型在GC需要的情况下都是可以被GC掉的,所以可以使用 exclude all phantom/weak/soft etc. references 只查看GC路径上的强引用

从对象到GC Roots的路径
在这里插入图片描述

9. Merge Shortest Paths to GC roots

从GC Roots到对象的共同路径
在这里插入图片描述
就是第8项:Path To GC Roots,顺序反过来

需要注意的是,Paths to GC roots是针对单个对象的,故在Histogram视图无法使用,因为Histogram视图是针对类的,只能使用Merge shortest Paths to GC roots查询

10. Leak Suspects Report

内存泄漏怀疑,一般在overview中就会直接看一下是否有memory leak的可能
在这里插入图片描述

使用MAT分析线上内存泄漏案例

场景:

User服务线上间断发生cpu占用高的问题,在cpu占用高的时间内,机器被hang住了,在prometheus上看就是一个中断,负载均衡只有一台发生了问题,无法响应请求

分析:

发现cpu占用高,发现堆内存也很大,有2G,正常运行情况下应该只有几百M

使用MAT查看hprof
在这里插入图片描述
在unreachable object里面,发现有170个User实例
在这里插入图片描述

查看Object中的值,发现一个规律,那就是这些用户的cert_no全部为null

原因:

查看错误日志

报错result, returns more than one elements

at org.hibernate.jpa.internal.QueryImpl.getSingleResult(QueryImpl.java:539)

是在进行支付宝小程序联合登录的时候发生的,有一行代码是根据支付宝用户的身份证查询我们系统用户,但是如果支付宝用户的身份证返回为null,这样customUserRepository会去查询bs_custom_user表中所有cert_no为null的用户,而这样的用户在内存中有171万之多

在程序中debug的时候,会发现代码运行在这里的时候明显卡顿了很久,大约20秒,在这个期间就是jpa进行查询把这些对象放到内存中,然后由于一个对象无法接收这171万的用户,导致报错:result returns more than one elements

但这里要非常注意的是:

这171万的对象,放到了内存中,并且是unreachable的了,发生了memory leak内存泄漏

参考:

使用Eclipse Memory Analyzer Tool(MAT)分析线上故障(一) - 视图&功能篇

又一次线上OOM排查经过

在"Preferences=>Memory Analyzer"中勾选"Keep Unreachable Objects",删除索引文件Dump同路径下的所有".index",即可看到所有的对象。

参考:JVM故障分析及性能优化系列之七:使用MAT的Histogram和Dominator Tree定位溢出源

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值