Java中对象、数组和基本类型的确切引用大小

5
我希望了解对象在内存中真实分配的空间。
我举几个例子来解释:在使用64位JVM时,指针大小应为8字节,因此:
- 对象singletest = new Object(); 将花费8字节来引用对象加上对象本身的大小 - 对象arraytest = new Object[10]; 将花费8字节来引用存储数组的位置加上8 * 10字节来存储数组加上每个对象的大小 - int singleint = new int; 只需花费2字节,因为int是原始类型 - int[] arrayint = new int[10]; 将花费8字节来引用位置和10 * 2字节来引用元素
此外,这就是Java允许编写以下代码的原因:
int[][] doublearray = new int[2][];
int[0][] = new int[5];
int[1][] = new int[10];

实际上,数组会像对象一样生成一个引用(又称为指针),因此在声明时第二个维度的大小并不重要(且维度可以不同,它们之间没有联系)。然后所需的空间将为:对 doublearray 的引用(8字节),第一维仅是对第二维的引用,因此还需要8字节*2(第一维大小),最后是2字节*5加上2字节*10。
因此,如果有一个真正的类就像这样:
class Test {
   int a, b;
   int getA() {return A};
   void setA(int a) {this.a = a;}
   int getB() {return B};
   void setB(int b) {this.b = b;}
}

当我调用一个新的实例化来生成一个指针(或者称为引用,因为这是Java),会使用8字节的空间加上2+2字节的空间将整数存储到类中。
问题是:我是正确的还是完全胡说八道?此外,当我不实例化对象,只是声明它时,是否会为进一步使用分配8字节的空间?如果我赋予它null值呢?
与此同时,对于原始类型,我很确定只是声明就会分配请求的空间(如果我声明一个“int i”,那么我可以立即调用i++,因为没有使用引用,只是在“0”上设置了一部分内存)。
我在网上搜索没有得到明确的答案...我知道我提出了很多问题,但是任何帮助都将不胜感激!(也许我不是唯一感兴趣的人)

可能是如何获取Java对象的大小的简单方法?的重复问题。 - Ted Hopp
1个回答

11

使用64位JVM时,指针大小应为8字节。

实际上,除非您的最大堆大小为32 GB或更多,否则通常是32位。这是因为Java使用引用,而不是指针(每个对象都在8字节而不是1字节边界上)。

JVM可以根据使用的JVM和最大堆大小来更改引用的大小。

Object singletest = new Object(); 将占用8个字节来引用对象加上对象的大小。

该对象将使用约16个字节的堆。它可能会使用4个字节的栈,但也可能只使用寄存器。

Object arraytest = new Object[10];

这将使用约16字节的头部,加上10倍的引用大小(总共约56字节)。

int singleint = new int; 将只需要2个字节,因为int是一种原始类型。

int始终是32位,不能创建new的原始类型对象。由于它在栈上可以使用4字节或仅使用寄存器。

int[] arrayint = new int[10]; 将占用8个字节来引用位置和10 * 2个字节的元素。

同样,对象的大小可能与new Object[10]相同(56字节)。

int[][] doublearray = new int[2][];
int[0][] = new int[5];
int[1][] = new int[10];

我不会把它称为doublearray,因为这可能会与double[]混淆。

然而,doublearray的大小可能约为16 + 2 * 4,而对于填充,则为16 + 5 * 4 + 4和16 + 10 * 4。

在堆上分配的内存对齐到8字节边界。

我称之为“new”实例化,使用8个字节的指针(或将其命名为引用,因为这是Java),再加上2+2个字节将整数存储到类中。

该引用位于堆栈上,通常不包括在内。

对象有大约16个字节的头部,int值占用2 * 4个字节。

如果我只声明一个对象但不实例化怎么办

Java不允许您声明对象,只允许原始类型和引用。

如果我赋予null值呢?

那可以改变引用的值,但除此之外什么都不会发生。

如果我声明一个“int i”,那么我可以立即调用i++,因为没有使用引用,而只是将一部分内存设置为“0”

不会使用堆,可能不会使用堆栈(可能是4个字节)。如果代码没有任何作用,则JIT编译器可能会将其删除。

或许我不是唯一感兴趣的人

...但并不害怕提问。 ;)


谢谢! :) 这是我一直在寻找的回复!我正在注释每一个单词! :) - pierpytom
PS:我之前说错了,“new int”这个写法是真的存在的...我把int类型的32位大小和16位大小搞混了,但“new int”... - pierpytom
1
你有 C++ 的背景吗? ;) 事实上,64 位 JVM 可以使用 32 位引用,而且通常会这样做,即使对经验丰富的 Java 开发人员来说,这也可能令人惊讶。 - Peter Lawrey

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