Java和对象,数组和基元类型的精确引用大小

时间:2012-04-30 15:59:03

标签: java arrays memory pointers memory-consumption

我想知道对象在内存中分配的真实空间。

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

  • Object singletest = new Object();将占用8个字节来引用Object加上对象的大小
  • 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 + 2bytes来将整数存储到类中。

问题是:我是对的还是我写完废话?此外,当我没有实例化一个对象但我只是声明它时,将分配8个字节以供进一步使用?如果我指定一个空值怎么办?

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

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

1 个答案:

答案 0 :(得分:9)

  

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

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

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

  

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

该对象将使用大约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];

我不会称之为双重阵列,因为它可能与double[]

混淆

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

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

  

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

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

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

  

当我没有实例化一个对象但我只是声明它

Java不允许您声明对象,只声明基元和引用。

  

如果我指定空值怎么办?

这可能会改变引用的值,但是没有任何反应。

  

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

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

  

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

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