eclipse 使用MAT分析堆栈

1. 介绍

Eclipse MAT是eclipse提供的插件用于分析JAVA heap。试过不少分析heap的,可是没有比这个更好用的了。html

PS:在mac high sierra上直接下载独立运行的MAT貌似会出问题卡死,我是本地直接下载了个。java

请先阅读下MAT官方的DOC:MAT官方DOC浏览器

2. 基本概念

2.1 堆中包含的内容

  • All Objects:Class, fields, primitive values and references
  • All Classes:Classloader, name, super class, static fields
  • Garbage Collection Roots:Objects defined to be reachable by the JVM
  • Thread Stacks and Local Variables:The call-stacks of threads at the moment of the snapshot, and per-frame information about local objects

2.2 Shallow VS Retined heap

Shallow heap size : 对象自己占用的大小,不包含其引用的对象Retained heap: 对象自己大小加上其全部引用对象的真实大小dom

PS: 可见实际占用看见或者回收的空间要看Retained heapeclipse

2.3 Dominator Tree

一个Object构成的树(DAG),最顶端的节点的retained memory由其全部子节点构成,做用主要是方便找占用retained heap size最大的对象jsp

2.4 gc root

GC ROOT本质就是一个对象,这个对象包含了一系列必须保证活跃的引用(能够理解成一个DAG)。JVM的GC就是判断哪些不能被回收,剩下的所有回收就行。即,遍历全部对象作GC ROOT可达性分析,可达的则不回收,不可达的则进行GC。ide

用MAT文档里面的话来解释就是:A garbage collection root is an object that is accessible from outside the heap. The following reasons make an object a GC root学习

可做为gc root的对象,完整列表参考下MAT官方文档,我重点罗列几个ui

  1. JNI相关的对象和引用
  2. 静态变量
  3. 持有监视器锁的对象
  4. native栈上的对象和引用

2.5 一些选项说明

  • biggest object by retained size:显示在内存较大的对象信息
  • list objects -- with outgoing references : 查看这个对象持有的外部对象引用。
  • list objects -- with incoming references : 查看这个对象被哪些外部对象引用。
  • show objects by class -- with outgoing references :查看这个对象类型持有的外部对象引用
  • show objects by class -- with incoming references :查看这个对象类型被哪些外部对象引用
  • paths to gc root : 显示不一样类型引用(上文中提到的Strong ,soft,weak )到跟节点的路径。
  • merge shorest path to gc root : 合并最短路径到root节点。
  • java basics:
    • classloader 该对象对应的classloader信息 。
    • thread details :线程信息
    • thread stacks :线程堆栈
    • find String : 在这个对象中查询须要的字符串
    • group by : 根据某个字段统计出现的个数
  • leak Identification -- top consumers :几个大消耗内存的对象

另外计算retsined size也是很经常使用的功能,MAT默认不显示这一列,若是有须要的能够本身勾选算一下:spa

3. 实践

3.1 classloader内存泄漏排查

参考文献2和4讲了classloader内存泄漏问题排查方法,能够学习下。我没有内存泄漏的例子,可是实际过程当中有碰到个perm oom的问题。

例如产生一个perm gen OOM,就猜想可能由classloader内存泄漏引发。由于perm区主要就存放一些class元数据、静态变量。好比有时候载入了一些java agent,一些classloader载入了很多类,可是分配的perm gen过小,就致使perm gen OOM了。固然这个OOM也不必定是内存泄漏,多是分配的perm区真的过小了,我就碰到了这样的状况:

总共分配了32M的PERM,平时使用就达到了29M,由于开了个java agent多加了几M就直接OOM了,所以也顺便用MAT 分析了下heap

打开classloader浏览器

看classloader的retained size,合起来差不都32M的样子,有个叫ArthasClasssLoader的,就是我说的java agent,差很少占用2M。。也是本次OOM的罪魁祸首。

PS: classLoader和通常的Obect不太同样,右键勾选的时候会问你要看Class Loader自己的信息仍是其定义的Classses信息。class Loader自己信息若是查看Immediate Dominators信息的话只有个ROOT。这也很好理解,class Loader是rt.jar里面的,是经过boorstrap classloader加载的,属于system class,天然其gc不会依赖别的class,属于最dominant的class了

3.2 某些类一直没有被GC问题排查

有时候要看为何这个类没有被GC,不符合预期,那么只要看看他在哪些GC ROOT对象的引用链上。按照以下操做,这里我排除了一些虚、弱软引用,只关注强引用便可。由于其余程度弱的引用反正都会被GC的,不会是对象异常没被回收的罪魁祸首。

最后按照罗列出来的引用链,下钻去查看,确定最后会找到一个gc root object:

这里能够看到这个Java Local类型的对象就是以前罗列的能够做为gc root object的

3.3 immediate object和gc root来查找某个对象的root dominated not的区别

某个对象确定会关联一个immediate object,当这个immediate object的全部实例被GC后,那么这个对象也确定会被GC。经过以下方式查找关联的immediate object是最快。可是这种方式只能查找和哪一个immediate object关联,不能查看immediate object的引用信息。

若是须要查看immediate dominators的引用信息,还要按照以下操做,该dominator object有哪一个外部对象持有的引用,从而了解须要哪些对象

固然很容易联想到用GC ROOT查找也是能够的,只不过gc root查找的话展示的内容层次更多些,本质上同样的, 能够看到最后都是定位到ResuableIterator@)xe0a54ce0这个对象

3.4 查看某个对象dominate 了哪些对象

3.3节咱们是查看某个对象被其余什么对象和引用dominate。有时候须要查看某个对象dominate 哪些子对象也很简单,直接操做Open in Dominatoe Tree

3.5 线程相关

持有某个对象实例的线程,直接按照以下操做便可:

4. 总结

MAT功能强大,自己针对其主要用法配合一些应用场景作了一些介绍,更多能够本身再配合官方文档使用一番,增强理解。

参考资料

  1. 知乎提问R大的回答,理解gc root
  2. classloader内存泄露的总结
  3. Classloader leaks I – How to find classloader leaks with Eclipse Memory Analyser (MAT)
  4. Solve "PermGen space OutOfMemoryError"
相关文章
相关标签/搜索