Java对象数组大小

5

计算对象数组的内存大小时,以下代码会得到"使用了24字节",这符合预期,据我所知,其中包括:

4字节(元素指针)+ 16字节(对象头)+ 4字节(元素空间)= 24字节

// with JVM argument -XX:-UseTLAB
public static void main(String[] args) {
    long size = memoryUsed();
    Object[] o = new Object[]{1};
    //Object[] o = new Object[]{1L};
    size = memoryUsed() - size;
    System.out.printf("used %,d bytes%n", size);
    //Output: used 24 bytes
}

public static long memoryUsed() {
    return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
}

但是当元素类型更改为 Long(1L)时,结果令人困惑,大多数情况下是"使用了9,264字节",有人能帮助我吗?这两种元素类型之间的内存分配差异是什么?

// with JVM argument -XX:-UseTLAB
public static void main(String[] args) {
    long size = memoryUsed();
    //Object[] o = new Object[]{1};
    Object[] o = new Object[]{1L};
    size = memoryUsed() - size;
    System.out.printf("used %,d bytes%n", size);
    //Output: used 9,264 bytes
}

1
可能是因为创建第二个数组时,JVM需要加载额外的类(例如Long及其内部类Long.LongCache),这会消耗比您预期更多的内存。 - Thomas Kläger
可能是重复问题:在Java中,确定对象大小的最佳方法是什么? - Thomas Kläger
如果回答解决了您的问题,您可以在此处接受答案...请参阅此处的操作方式:https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work - Eugene
1个回答

1

有一种更好的方法来计算对象大小,因为有一个专门的工具叫做JOL

你对它的想法并不完全正确。该对象的总大小将为40字节。让我们看看这个空间是从哪里来的:

12 bytes headers (8 bytes + 4 bytes, since there are two headers)

你可能认为它是16字节(8+8),但实际上默认情况下启用了压缩指针选项。你可以通过-XX:-UseCompressedOops禁用它,这种情况下头部的大小确实会变成16字节
4 bytes size of the array (arrays have an int size that is stored in headers)
4 bytes is the reference size of the Integer (1)
4 bytes alignment (since objects are 8 bytes aligned - this is the trick behind CompressedOops btw)

到目前为止,你的数组有24个字节
现在,你在其中存储了一个整数,它也是一个对象,因此:
12 bytes headers
4 bytes for the actual int value inside Integer

因此,总大小为40字节

这个数组中存储的整数可能是其原始类型,因此它保存了额外的16字节对象头。 - 鄭无爲
@鄭无爲,你将其声明为“Object”,因此它将是“Integer”;如果你想节省空间,需要将其声明为“int[]”。 - Eugene

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接