Java 以及对象、数组和基元类型的确切引用大小



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

我尝试用一些例子来解释:使用 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];

真正发生的是,数组将像对象一样生成引用(又名指针(,因此在声明时第二个维度的大小并不重要(维度可以不同,它们之间没有链接(。那么占用的空间将是:对双数组(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 个字节的指针(或将其命名为 reference,因为它是 Java(加上 2+2 字节将整数存储到类中。

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

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

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

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

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

JVM

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

Object

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

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

对象数组测试 = 新对象[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 + 2 * 4,对于填充,尺寸约为16 + 5 * 4 + 4

(用于填充(和16 + 10 * 4。

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

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

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

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

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

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

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

这可能会更改引用的值,但除此之外什么都不会发生。

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

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

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

。但并不害怕问。;)

最新更新