Mat 用法

MAT

MAT工具全称为Memory Analyzer Tool,一款详细分析Java堆内存的工具,该工具非常强大,为了使用该工具,我们需要hprof文件.

HPROF文件存储的是特定时间点,java进程的内存快照。有不同的格式来存储这些数据,总的来说包含了快照被触发时java对象和类在heap中的情况。由于快照只是一瞬间的事情,所以heap dump中无法包含一个对象在何时、何地(哪个方法中)被分配这样的信息。

几个关键概念

  • Histogram:列出内存中的对象,对象的个数以及大小
  • Dominator Tree:列出最大的对象以及其依赖存活的Object (大小是以Retained Heap为标准排序的)
  • Top Consumers : 通过图形列出最大的object
  • Duplicate Class:通过MAT自动分析泄漏的原因
  • Shallow heap : 对象本身占用内存的大小,不包含其引用的对象。
    (常规对象(非数组)的Shallow size有其成员变量的数量和类型决定。数组的shallow size有数组元素的类型(对象类型、基本类型)和数组长度决定. 因为不像c++的对象本身可以存放大量内存,java的对象成员都是些引用。真正的内存都在堆上,看起来是一堆原生的byte[], char[], int[],所以我们如果只看对象本身的内存,那么数量都很小。所以我们看到Histogram图是以Shallow size进行排序的,排在第一位第二位的是byte,char 。)
  • Retained Heap : 它表示如果一个对象被释放掉,那会因为该对象的释放而减少引用进而被释放的所有的对象(包括被递归释放的)所占用的heap大小。
    (于是,如果一个对象的某个成员new了一大块int数组,那这个int数组也可以计算到这个对象中。相对于shallow heap,Retained heap可以更精确的反映一个对象实际占用的大小(因为如果该对象释放,retained heap都可以被释放)。)
  • outgoing references :表示该对象的出节点(被该对象引用的对象)。
  • incoming references :表示该对象的入节点(引用到该对象的对象)。
  • GC Root: GC发现通过任何reference chain(引用链)无法访问某个对象的时候,该对象即被回收。所以JVM就是GC Roots。
  • Unreachable指的是可以被垃圾回收器回收的对象,但是由于没有GC发生,所以没有释放,这时抓的内存使用中的Unreachable就是这些对象。

1. 预览信息

打开dump 文件,通常我们需要关注一下几个重要信息, 内存占用饼图,Actions部分的Histogram, Top Consumers.
我们打开Top Consumers,会生成一个报告,我们可以Biggets Objects overview, 能够看到主要内存占用者

Paste_Image.png

 

点击下面的biggest Objects 可以查看具体的地址。
还有Biggest Top Level Dominator Classes , 可以看到主要占用内存的都是些什么东东。

2. dump分析

2.1 Histogram

MAT中Histogram的主要作用是查看一个instance的数量,一般用来查看自己创建的类的实例的个数。 可以分不同维度来查看对象的Dominator Tree视图,Group by class、Group by class loader、Group by package 和Histogram类似,时间久了,通过多次对比也可以把溢出对象找出来。 Histogram 中可以分Group,Thread 区分信息。 通常为:选中某一项-> show objects and class -> by incoming reference->merge shortest path to gc root -> exclude weadk reference
等流程来查看具体情况。

可以在上面过滤相关包名,查看到具体类型, 关注objects个数, 表示内存dump 中有多少个相关类型对象, 比如不改存在的 对象存在了,或者有的对象内存中有太多的份数, 这样就可以进行一个全面分析。

也可以选择Group by package ,这样方便根据package来进行分析。

 

Paste_Image.png

也可以选择thread来进行分析, 这样查看占用内存最多的线程,这些线程可能为有内存问题的线程。

点击右键常用的几个选项:

  • List Objects -> with incoming references 查看这个对象被哪些外部对象引用
  • List Objects-> with outcoming references 查看这个对象持有的外部对象引用
  • Path to GC Roots -> exclude ... references 查看这个对象的GC Root,不包含xxx引用,剩下的基本就是强引用了。因为只有强引用一直存在,gc就一直无法回收该对象,从而也就出现内存泄露。
  • Merge shortest path to GC root 找到从GC根结点到一个对象或者一组对象的共同路径。从这里可以查看到对象的引用关系。

2.2 Debug Bitmap

图片一直是内存占用的一个大头,也是引起内存泄露,OOM的常客。所以对图片的分析是需要非常了解,这样才能更好的优化项目。*注意:图片在内存中占用的大小:ARGB_8888 类型的图片 为 内存中图片宽度*内存中图片高度4, 此处需要注意原始图片宽高和内存图片宽高不一致,包括拉伸和压缩,尤其是图片位置放错,比如1080p设备,xxxhdpi下面没有图片,会去别的目录下寻找图片,此时将会对图片拉伸。 **
下面我们来看一下图片的处理。通常dump信息中图片表现为两种类型,Bitmap, byte[]。我们需要知道该图片是哪张图片,这样才能好优化相关的图片代码。

  • Bitmap类型
    在mat中通常能够看到bitmap类型,占用了大量的内存,如下面这张图片,在内存中占用2M。 我们可以打开,查看mBuffer变量。

     

    Paste_Image.png

选中mBuffer-> 右键选中Copy-> 选择Save Value To File -> 生成一个xxx.data 文件。

  • Byte[] 类型
    如下,查看byte的 in comming, 即可看到它是一个bitmap,此时如下图,我们可以直接将该byte数据写入xxx.data 文件。

     

    Paste_Image.png

下一步是选中对应的bitmap,打开Inspector 窗口,查看bitmap的尺寸,并且使用GIMP工具(可以安装一个,开源的)打开刚才的data文件,图像类型选择RGB Alpha, 宽度和高度填入图像的宽高,打开即可。

Paste_Image.png

Paste_Image.png

2.3 堆对比

通常为了分析内存是否泄露,内存是否持续增长但没有释放等问题,我们需要dump两次来进行内存堆的对比。

打开两个或多个dump文件,打开Navigation History视图,点击Historgam,选择Add to Comp are Basket,最后选中Compare the Result 。

Paste_Image.png

在对比结果中,主要分析类型或者对象的数量是否有变化, 内存是否有变化。

通过以上手段,我们可以定位到大部分内存问题。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值