现在的位置: 首页 > 综合 > 正文

Java内存分析(2)分析Heap Dump

2012年03月12日 ⁄ 综合 ⁄ 共 1680字 ⁄ 字号 评论关闭

在这里,我们借助了Eclipse的Memory Analyzer工具,以便获得智能的便于分析的效果图。先下载安装好工具下载地址

下面来装备内存素材,从简单的开始。假设有一个类,这个类里面不包含任务其它的信息,空的:

public class Node{}
然后是一个Mail函数
public class Main{
	public static void main(String[] args){
		Node n = new Node();
	}
}
运行程序,并用上一篇文章中提及的方式获取一个内存的转储文件。然后运行Eclipse Memory Analyzer Tool(MAT),并用其打开转储文件。

你将看到如下的内容:

heap1

这个页面显示出了该转储文件中的一些概要信息,如哪些对象占用的内存比例比较多之类。通过点击这些图片,你可以看到更详细的报告。

但是我们先关注一下内存的组织图(其实没有图,更确切的说是个报表的样式了),点击Histogram按钮(上图中的红色区域)。然后在Class Name一栏中输入"Node”并回车,这样就会显示我们刚才自己定义的类的信息了。

heap1_1

那这些信息说明了些什么?

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的倍数,也就是说至少是一个字节。

刚才我们用一个最简单的对象来说明一些术语,现在我们来尝试往这个空的类中慢慢地加入一些东西试试。

public class Node{
	private int fInt = 0;
}

加入一个java的primitive int 类型,看看会有什么变化:

WithIntField

 

再加入一个长整型:

public class Node{
	private int fInt = 0;
	private long fLong = 0L;
}

WintIntLongFields

似乎我们每增加一个字段,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

NodeObj的Retained Set要远大于Node的,但它们的Shallow Heap却是相同的。那看看NodeObj的Retained Set中有哪些元素呢?【选中NodeObj->右键->Show Retained Set】

heap4_2

原来是因为有Integer和Long的原因。

至此,大家应该对MAT中的基本概念及使用方式有所了解了,后面会继续说明一下MAT的高级用途。

抱歉!评论已关闭.