MAT内存分析工具
MAT是MemoryAnalyzerTool的简称,它是一款功能强大的Java堆内存分析器,可以用于查找内存泄漏以及查看内存消耗情况。MAT是
基于Eclipse开发的一款免费的性能分析工具,读者可以在 http://www.eclipse.org/mat/上下载并使用MAT。
一,初识MAT
在分析堆快照前,首先需要导出应用程序的堆快照。在本书前文中提到的jmap、JConsole和VisualVM等工具都可以用于获得Java应用程序的堆快照文件。此外,MAT本身也具有这个功能。
如图6.66所示,在File菜单中选择AcquireHeapDump命令,在弹出对话框的当前Java应用程序列表中选择要分析的应用程序即可,如图6.67所示。
除了直接在MAT中导出正在运行的应用程序堆快照外,也可以通过File菜单中的OpenHeapDump命令打开一个既存的堆快照文件。
注意:使用MAT既可以打开一个已有的堆快照,也可以直接从活动Java程序中导出堆快照。
图6.68所示为正常打开堆快照文件后的MAT界面。
在图6.68的右侧界面中显示了堆快照文件的大小、类、实例和ClassLoader的总数;饼图中显示了当前堆快照中最大的对象。将光标悬停在饼图中,可以在左侧的Inspector界面中查看该对象的详细信息。在饼图中单击,可以对选中的对象进行更多的操作。
单击工具栏上的柱状图按钮(如图6.69所示),可以查看当前堆的类信息,包括类的对象数量、浅堆(Shallow)大小和深堆(Retained)大小,如图6.70所示。
通过柱状图界面,可以查找引用选中对象的对象集合以及选中对象所引用的对象集合。如图6.71所示,选中java.util.Vector对象并右击,在弹出的右键菜单中选择Listobjects命令,弹出的withoutgoingreferences和withincomingreferences子命令分别表示查找java.util.Vector实例的引用对象,以及引用java.util.Vector实例的对象。
注意:通过MAT,可以根据对象间的引用关系对内存中的对象进行分析。
图6.72显示了选择withincomingreferences命令后的输出结果,展示了两个被主线程引用的java.util.Vector局部变量实例。
为了方便查看,柱状图还可以根据ClassLoader和包对类进行排序。图6.73显示了MAT的柱状图排序功能,以及一个按照包进行排序的柱状图输出命令。
图6.72 引用关系查询结果
二,浅堆和深堆
浅堆(ShallowHeap)和深堆(RetainedHeap)是两个非常重要的概念,它们分别表示一个对象结构所占用的内存大小和一个对象被执行GC操作后,可以真实释放的内存大小。
浅堆是指一个对象所消耗的内存。在32位系统中,一个对象引用会占据4个字节,一个int类型会占据4个字节,long型变量会占据8个字节,每个对象头需要占用8个字节。
根据堆快照格式不同,对象的大小可能会向8字节进行对齐。以String对象为例,图6.74显示了String对象的几个属性。
3个int类型以及一个引用类型合计占用的内存为3×4+4=16字节,再加上对象头的8个字节,因此String对象占用的空间,即浅堆的大小是16+8=24字节。浅堆的大小只与对象的结构有关,与对象的实际内容无关。也就是说,无论字符