5

我想确切地知道在内存中为对象分配的实际空间。

我试着用一些例子来解释:使用 64 位 JVM,指针大小应该是 8 个字节,所以:

  • Object singletest = new Object();将需要 8 个字节来引用对象加上对象的大小
  • Object 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;}
}

当我调用 new 进行实例化时,将使用 8 个字节的指针(或将其命名为引用,因为它是 Java)加上 2+2 个字节将整数存储到类中。

问题是:我是对的还是我写的都是废话?此外,当我不实例化一个对象而只是声明它时,是否会分配 8 个字节以供进一步使用?如果我分配一个空值怎么办?

同时对于原始类型,我很确定只要声明它就会分配请求的空间(如果我声明一个“int i”,那么我可以立即调用 i++,因为没有使用引用,只有一部分内存设置为“0” )。

我在互联网上搜索没有聪明的回应......我知道我写了很多问题,但任何帮助将不胜感激!(也许我不是唯一感兴趣的人)

4

1 回答 1

10

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

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

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

对象单测试 = 新对象();将需要 8 个字节来引用对象加上对象的大小

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

对象数组测试=新对象[10];

这将使用大约 16 个字节作为标头,加上 10 倍的参考大小(总共大约 56 个字节)

整数单整数 = 新整数;只需要 2 个字节,因为 int 是原始类型

int始终是 32 位,您无法创建new原语。由于它在堆栈上的概念,它可能使用 4 字节的堆栈,或者它可能只使用一个寄存器。

整数 [] 数组整数 = 新整数 [10]; 将需要 8 个字节来引用位置和 10*2 字节来引用元素

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

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

我不会称它为双数组,因为它可能会与double[]

然而,大小可能约为 16 + 2 * 4doublearray和 16 + 5*4 + 4(用于填充)和 16 + 10 * 4。

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

我调用一个 new 来实例化,一个 8 个字节的指针(或将其命名为引用,因为它是 Java)将用于加上 2+2 个字节来将整数存储到类中。

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

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

当我不实例化一个对象但我只是声明它时

Java 不允许您声明对象,只有原语和引用。

如果我分配一个空值怎么办?

这可能会改变引用的值,但否则什么也不会发生。

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

不会使用堆,也可能不会使用堆栈(可能是 4 个字节)。如果 JIT 编译器不执行任何操作,它可能会删除代码。

也许我不是唯一一个感兴趣的人

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

于 2012-04-30T16:01:39.553 回答