对象、数组和原始类型的 Java 和精确引用大小

标签 java arrays memory pointers memory-consumption

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

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

  • Object singletest = new Object(); 将占用 8 个字节来引用 Object 加上 Object 的大小
  • Object arraytest = new Object[10];会占用8个字节来引用数组存储的位置加上8*10个字节来存储数组加上每个Object的大小
  • 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”)。

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

最佳答案

using a 64 bit JVM, pointer size should be 8 bytes,

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

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

Object singletest = new Object(); will take 8 bytes to reference the Object plus the size of the Object

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

Object arraytest = new Object[10];

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

int singleint = new int; will take just 2 bytes, because int is a primitive type

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

int[] arrayint = new int[10]; will take 8 bytes to reference the position and 10*2 bytes for the elements

同样,该对象的大小可能与 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 字节边界对齐。

I call a new to instantiate, a pointer (or name it reference, because it's Java) of 8 bytes will be used plus 2+2bytes to store the integers into the class.

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

该对象有一个大约 16 个字节的 header ,int 值占用 2 * 4 个字节。

when I don't instantiate an object but I just declare it

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

what if I assign a null value?

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

if I declare an "int i" then I can immediately call i++ because no reference are used, just a portion of memory is setted on "0"

不会使用堆,也可能不会使用栈(可能是 4 个字节)。如果 JIT 编译器什么都不做,它可能会删除代码。

maybe I'm not the only one interested

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

关于对象、数组和原始类型的 Java 和精确引用大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10386696/

相关文章:

java - 当我创建的类需要一个 int 数组时,我如何传递一个 String 数组(包含 : , 字母、数字和空格)?

java - 在 Java 中执行 shell 命令行

debugging - 如果图像在只读内存中,调试器如何设置断点?

memory - Little Endian 与 Big Endian 架构

c - Linux SPARSEMEM 内存模型真的很稀疏吗?

java - 如何将几个 "Sqrt[some text inside]"变成几个 Sqrt(里面有一些文字),我的意思是从 [] 变成 ()

java - 如何在 JavaFX 中使用 try-catch?

javascript - JS/ES6 : Object to Array conversion

c - 如何声明一个大小为 2^18 的结构数组

Ruby、数组、对象 - 选择对象