我们可以使用 jmap –histo 这种命令去分析哪些对象占据着我们的堆空间。但是那是比较容易分析的问题,如果是遇到内存情况比较复杂
的情况,命令的方式是看不出来的,这个时候我们必须要借助一下工具。当然前提是通过 jmap 命令把整个堆内存的数据 dump 下来。包括jdk自带的内存分析工具VisualVM,分析的数据非常有限。
MAT 简介
MAT 工具是基于 Eclipse 平台开发的,本身是一个 Java 程序,是一款很好的内存分析工具,所以如果你的堆快照比较大的话,则需要一台内存比较大的分析机器,并给 MAT 本身加大初始内存,这个可以修改安装目录中的 MemoryAnalyzer.ini 文件。
柱状图
MAT 中的 Incoming/Outgoing References
在柱状图中,我们看到,其实它显示的东西跟 jmap –histo 非常相似的,也就是类、实例、空间大小。
但是 MAT 有一个专业的概念,这个可以显示对象的引入和对象的引出。
在 Eclipse MAT 中,当右键单击任何对象时,将看到下拉菜单。如果选择“ListObjects”菜单项,则会注意到两个选项:
with incoming references 对象的引入
with outgoing references 对象的引出
举一个例子·
class A {
private C c1 = C.getInstance();
}
class B {
private C c2 = C.getInstance();
}
class C {
private static C myC = new C();
public static C getInstance() {
return myC;
}
private D d1 = new D();
private E e1 = new E();
}
class D {
}
class E {
}
public class MATRef {
public static void main(String[] args) throws Exception {
A a = new A();
B b = new B();
Thread.sleep(Integer.MAX_VALUE);//线程休眠
}
}
代码中对象和引用关系如下:
对象 A 和对象 B 持有对象 C 的引用
对象 C 持有对象 D 和对象 E 的引用
我们具体分析对象 C 的 Incoming references 和 Outgoing references 。
1、 程序跑起来
2、 MAT 连接上正在运行的进程
我们 再来分析下 outgoing reference
这个 outgoing references 和 incoming references 非常有用,因为我们做 MAT 分析一般时对代码不了解,排查内存泄漏也好,排查问题也好,垃圾回收中有一个很重要的概念,可达性分析算法,那么根据这个引入和引出,我就可以知道这些对象的引用关系,在 MAT 中我们就可以知道比如 A,B,C,D,E,F 之间的引用关系图,便于做具体问题的分析。GCRoot根据引用关系垃圾回收。
MAT 中的浅堆与深堆
<