在这里,我们借助了Eclipse的Memory Analyzer工具,以便获得智能的便于分析的效果图。先下载安装好工具下载地址。
下面来装备内存素材,从简单的开始。假设有一个类,这个类里面不包含任务其它的信息,空的:
public class Node{}
public class Main{ public static void main(String[] args){ Node n = new Node(); } }
你将看到如下的内容:
这个页面显示出了该转储文件中的一些概要信息,如哪些对象占用的内存比例比较多之类。通过点击这些图片,你可以看到更详细的报告。
但是我们先关注一下内存的组织图(其实没有图,更确切的说是个报表的样式了),点击Histogram按钮(上图中的红色区域)。然后在Class Name一栏中输入"Node”并回车,这样就会显示我们刚才自己定义的类的信息了。
那这些信息说明了些什么?
Objects是指内存中,该类型的对象有多少个
Shallow Heap是指该对象占用了多少内存(字节)。一个对象的引用往往需要32或64比特(bit)(基于不同的平台实现,该值也会不同),整型需要占用4字节,长整型8字节。这些是JVM规范里规定,但不同JVM实现可以按照自己方式来存储数据。另外,基于不同的Heap Dump格式,这些值也可能会有变化,但往往会更加真实地反应出内存的占用量。
Retained Set(保留集)指的是一个对象集合。假定一些对象会由于对象X被垃圾回收(GC)后,也同时需要被GC掉,那么这些对象就属于X的Retained Set。注意,Retained Set是包含X本身的。
Retained Heap是指如果该对象被回收,可以简单地理解为对象的Retained Set中的对象所占用的内存的总和。
好了,我们再来看一下上面的图。cm.demo.mat.Node只有一个对象,占用的内存为16bit(2个字节),其Retained Heap是16(Retained Heap没有自动计算出来,你可以选中某一项,然后右键->Calculate Precise Retained Set)。但是需要注意的是,Shallow Heap的实际值与转储文件的格式相关,同时在转储时,会把这个值进行处理以更好地反应实际的内存占用量。但不管怎么说,这个值始终会是8的倍数,也就是说至少是一个字节。
刚才我们用一个最简单的对象来说明一些术语,现在我们来尝试往这个空的类中慢慢地加入一些东西试试。
似乎我们每增加一个字段,Node的内存占用量就会增加一个字节。
再换一种方式,假如将primitive的int和long换成java.lang.Integer和java.lang.Long呢,结果会不会是一样?!试试!
public class NodeObj{ private Integer fInt = 0; private Long fLong = 0L; }
public class Main{ public static void main(String[] args){ Node n = new Node(); NodeObj no = new NodeObj(); } }
![heap4_1 heap4_1](https://images.cnblogs.com/cnblogs_com/ungshow/201204/201204081633273761.png)
NodeObj的Retained Set要远大于Node的,但它们的Shallow Heap却是相同的。那看看NodeObj的Retained Set中有哪些元素呢?【选中NodeObj->右键->Show Retained Set】
原来是因为有Integer和Long的原因。
至此,大家应该对MAT中的基本概念及使用方式有所了解了,后面会继续说明一下MAT的高级用途。