MAT 工具是基于 Eclipse 平台开发的,本身是一个 Java 程序,是一款很好的内存分析工具,所以如果你的堆快照比较大的话,则需要一台内存比较大的分析机器,并给 MAT 本身加大初始内存,这个可以修改安装目录中的 MemoryAnalyzer.ini 文件。
柱状图
MAT 中的 Incoming/Outgoing References
在柱状图中,我们看到,其实它显示的东西跟 jmap –histo 非常相似的,也就是类、实例、空间大小。 但是 MAT 有一个专业的概念,这个可以显示对象的引入和对象的引出。 在 Eclipse MAT 中,当右键单击任何对象时,将看到下拉菜单。如果选择“ListObjects”菜单项,则会注意到两个选项: with incoming references 对象的引入 with outgoing references 对象的引出
举一个例子·
classA{private C c1 = C.getInstance(); } classB{private C c2 = C.getInstance(); } classC{privatestatic C myC =newC();publicstatic C getInstance(){return myC;}private D d1 =newD();private E e1 =newE(); } classD{ } classE{ } publicclassMATRef{publicstaticvoidmain(String[] args)throws Exception {A a =newA();B b =newB();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根据引用关系垃圾回收。
classA{privatestaticbyte[] b =newbyte[10*1000];private B b1 =newB();private C c1 =newC(); } classB{private D d1 =newD();private E e1 =newE(); } classC{private F f1 =newF();private G g1 =newG(); } classD{ } classE{ } classF{ } classG{ }publicclassMATHeap{publicstaticvoidmain(String[] args)throws Exception {A a =newA();Thread.sleep(Integer.MAX_VALUE);//线程休眠} }
对象 A 持有对象 B 和 C 的引用。 对象 B 持有对象 D 和 E 的引用。 对象 C 持有对象 F 和 G 的引用。 Shallow Heap 大小 请记住: 的 对象的 Shallow heap 是其自身在内存中的大小 。实际大小参照真实数据,上图画图的是虚拟数据举的例子方便计算。
引用变动的影响 在下面的示例中,让对象 H 开始持有对 B 的引用。注意对象 B 已经被对象 A 引用了。假设D的对象大小为8byte字节的10倍
在这种情况下,对象 A 的 的 Retained heap 的 大小将从之前的 70 到 减小到 40 个字节。如果对象 A 被垃圾回收了,则将仅会影响 C、F 和 G 对象的引用。因此,仅对象 C、F 和 G 将被垃圾回收。另一方面,由于 H 持有对 B 的活动引用,因此对象 B、D 和 E 将继续存在于内存中。因此,即使 A 被垃圾回收,B、D 和 E 也不会从内存中删除。因此,A 的 Retained heap 大小为:= A的 shallow heap 大小 + C 的 shallow heap 大小 + F 的 shallow heap 大小 + G 的 shallow heap 大小 = 10 bytes + 10 bytes + 10 bytes + 10 bytes = 40bytes.(数据是假设出来的,正常应该是8字节的倍数大小,这里便于计算理解)
MAT 支持一种类似于 SQL 的查询语言 OQL(Object Query Language),这个查询语言 VisualVM 工具也支持。
查询 A 对象: select * from ex14.ObjectsMAT$A 查询包含 java 字样的所有字符串: select * from java.lang.String s where toString(s) like “.java.” OQL 有比较多的语法和用法,若想深入了解,可以了解这个网址 http://tech.novosoft-us.com/products/oql_book.htm 案例分析