Java中的字节默认情况下占用4个字节?

可能重复:
内存中字节的大小 – Java

我在一篇文章中读到了这个。 我只是按原样粘贴:

  • 该类占用至少8个字节。 所以,如果你说**new Object();**你将在堆上分配8个字节。
  • 每个数据成员占用4个字节,long和double除外,占用8个字节。 即使数据成员是一个字节,它仍然会占用4个字节! 此外,使用的内存量以8字节块增加。 因此,如果你有一个包含一个字节的类,它将占用该类8个字节,数据占8个字节,总共16个字节(呻吟!)。

它是真的Java字节分配/占用4个字节? 而空类需要8个字节? 这里也很混乱。

这是错误的,至少对于HotSpot JVM而言。 在那里,类中的原始字节字段将占用一个字节,但是类的实例的大小确实从8个字节开始,并且字段被分组为每个占用8个字节的块 – 例如,您可以不要跨越8字节边界分割字段。

参见例如http://www.codeinstructions.com/2008/12/java-objects-memory-structure.html

由于Java规范不要求使用内存,这取决于您使用的JVM实现。

当然,在所有JVM实现中都会存在每个对象的开销(例如,实现运行时类型检查)。 JVM可能会选择内存对齐字段(在某些平台上,这会在访问字段时提供显着的加速)。

但是,如果数组成员填充内存对齐,并且可以确认(至少在oracle vm for windows上)boolean []每个元素占用一个字节,我会非常惊讶。

此外,值得注意的是,如果您恰好处理适当大的堆,则引用类型字段的大小可以是8个字节。

总结:如果您真的想知道,请测量目标JVM上的内存消耗。

编辑:出于好奇,我写了一个小的(不准确的)基准:

 class FourBytes { byte a,b,c,d; } public class Test { long usedBefore = used(); long used() { return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); } public void before() { System.gc(); usedBefore = used(); } public void after(String text) { long usedAfter = used(); System.out.println(text + "\t" + new BigDecimal(usedAfter - usedBefore).movePointLeft(6) + " bytes"); before(); } { int max = 1000000; before(); boolean[] bools = new boolean[max]; after("boolean in array"); char[] chars = new char[max]; after("char in array "); Object[] objects = new Object[max]; after("reference type in array"); for (int i = 0; i < max; i++) { objects[i] = new Object(); } after("Object instance "); Byte[] bytes = new Byte[max]; before(); for (int i = 0; i < max; i++) { bytes[i] = new Byte((byte) i); } after("Byte instance "); Integer[] integers = new Integer[max]; before(); for (int i = 0; i < max; i++) { integers[i] = new Integer(i); } after("Integer instance"); FourBytes[] fbs = new FourBytes[max]; before(); for (int i = 0; i < max; i++) { fbs[i] = new FourBytes(); } after("FourBytes instance"); } public static void main(String[] args) throws Exception { new Test(); } } 

 java version "1.7.0_02" Java(TM) SE Runtime Environment (build 1.7.0_02-b13) Java HotSpot(TM) Client VM (build 22.0-b10, mixed mode, sharing) 

它打印:

 boolean in array 1.183624 bytes char in array 2.091768 bytes reference type in array 4.091768 bytes Object instance 8.023664 bytes Byte instance 16.133408 bytes Integer instance 16.147312 bytes FourBytes instance 16.142568 bytes 

该类占用至少8个字节。 所以,如果你说新的Object(); 你将在堆上分配8个字节。

在OpenJDK / HotSpot JVM中,它将在32位JVM上使用8个字节,在64位JVM上使用16个字节。

每个数据成员占用4个字节,long和double除外,占用8个字节。

最小大小为1字节而不是4字节。 即使在64位JVM上,引用也特别使用4个字节。

即使数据成员是一个字节,它仍然会占用4个字节!

这是一个新想法。 我不知道你会如何得出这个结论。

此外,使用的内存量以8字节块增加。

从技术上讲,它与8字节边界对齐。

因此,如果您有一个包含一个字节的类,则该类将占用8个字节

对于32位或64位JVM中的标头,该字节将占用8或12个字节,该字节将占用1个字节,并向上舍入到下一个8字节边界。

和8个字节的数据,总共16个字节(呻吟!)。

确实,但是每个可能的Byte对象都被缓存并自动装箱,没有理由你会这样做。 您永远不需要显式或甚至隐式地创建字节。

 Byte b = new Byte((byte) 1); // bad idea. Byte b = 1; // simpler and more efficient byte b = 1; // the most efficient option.