上一篇: 我到底需要多少内存(part 1) - 什么是retained heap?
原文: http://plumbr.eu/blog/how-much-memory-do-i-need-part-2-what-is-shallow-heap
一个特定的数据结构的大小是多少?
"我可以把所有这些对象放到我的ehCache中吗?"
这篇文章是我们试着回答那些问题系列的第二篇.上一篇文章解释了一个对象的retained heap和shallow heap的不同.在文章中我们也提供了一个例子如何去计算一个数据结构的retained heap.在今天的这篇文章中我们将扩展我们在前面称为"simple"的问题. 换句话说 - 如何去估算一个对象的shallow heap.
在第一篇文章中我们推开一大堆复杂性说明计算shallow heap的大小是很容易的 - 它只包含对象本身占用的堆.但是如何计算这个对象"它自己"需要多少堆内存?显示有一个工式:
Shallow Heap的大小 = [类的引用] + 父类字段的大小 + 实例字体的大小 + [对齐]
似乎没有太大的帮助,是吧?我们使用下面的示例代码去尝试工作:
class X {
int a;
byte b;
java.lang.Integer c = new java.lang.Integer();
}
class Y extends X {
java.util.List d;
java.util.Date e;
}
现在,我们努力回答一下这个问题 - 一个Y实例需要多少shallow heap?我们开始计算它,假定我们在一个32位的系统架构上:
开始 - Y是X的子类,所以它的大小包含了来自父类的"某些东西".因此,在计算Y大小的之前,我们先计算X的shallow heap的大小.转入关于X的计算,前8个字节被用作类的引用.这个引用在所有的Java对象中一直存在是被JVM用来定义后续状态的内存布局.它有三个实例变量 - 1个int,1个Integer和1个byte.这些实例变量需要的堆如下:
1. byte应该是什么.在内存是就是1个字节.
2. int在32位架构中需要4个字节.
3. Integer的引用也需要4个字节.注意当计算retained heap的时候,我们也会考虑包装到Integer对象中的原始类型的大小,但是我们在这计算shallow heap的大小,我们只需要4个字节的引用.
所以 - 是这样吗?X的shallow heap是类的引用8个字节 + 1个字节(byte) + 4个字节(int) + 4个字节(Integer的引用) = 17个字节?实事上 - 不对.现在被称为对齐的(也叫补齐)开始发挥作用了. 意思是JVM分配内存是8字节的倍数,所以我们创建一个X实例是分配24个字节而不是17个字节.
如果你可以跟着我们一直到这,很好,不过现在我们要试着做一些更加复杂的.我们不是创建X实例,而是创建Y实例.意思是 - 我们可以减掉8个字节的类引用和补齐的值.这个可能不太明显但是 - 你是否有注意到当计算X的shallow heap大小的时候我们没有考虑所有的类都是继承了java.lang.Object如果你没有在你的代码中显式的说明.我们没有考虑父类的header,因为JVM足够聪明去检查来类自己的定义,而不是去复制到对象的header.
这同样适用于补齐 - 当创建一个对象你只要补齐一次,而不是在父类/子类的边界.所以我们可以说当创建一个X子类你将只继承到来自实例变量的9个字节.
最后我们回到最初的任务开始计算Y的大小.正好我们看到的,我们已经丢失了父类的9个字节.让我们看一下当我们真实的构造一个Y的实例将会增加些什么.
1. Y的header参见它的类定义占用的8个字节.和前面的一个相同.
2. Date是一个对象的引用.4个字节.简单.
3. List是一个容器的引用.也是4个字节.无关紧要.
所以除了来自父类的9个字节我们还有来自header的8个字节,来自两个引用(List和Date)的2*4个字节.Y实例的总的shallow heap的大小会是25个字节,补齐到32个字节.
要使计算容易点,我们已经汇总如下图:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Align | Align | Align | Align | |||||||||||||||||||||||||||||
X | Object | a | b | c | ||||||||||||||||||||||||||||
Y | Object | a | b | c | d | e |
有了这些知识你可以做什么?连同计算retained heap大小的能力,你现在拥有终极力量去计算你的数据结构真正需要多少内存.