我知道如何通过添加三个部分来计算Java对象的内存大小:头+属性+引用。
我也知道Java数组也是一个对象。
但是当我读到“理解JVM高级特性和最佳实践,第二版”时,它说Java数组的头由三个部分组成:标记word、类指针和数组长度。
在Hotspot 64位JVM中,它总是24字节。
但是在32位JVM中,如何计算Java数组的内存大小?
我希望你们能给我一些Java代码示例,向我展示如何计算对象的内存大小,而不是仅限于数组对象。
发布于 2018-05-24 12:18:36
实际的对象大小是特定于实现的,甚至不要求对象的所需大小在其生存期内保持不变。
有一篇关于wiki.openjdk.java.net的文章声明:
对象标头布局 对象标头由本机大小的标记字、klass字、32位长字(如果对象是数组)、32位间隙(如果对齐规则需要)、以及零或多个实例字段、数组元素或元数据字段组成。(有趣的问题: Klass元对象包含紧跟在klass单词之后的C++ vtable。) 如果存在gap字段,则通常可用于存储实例字段。 如果UseCompressedOops是假的(在ILP32系统中总是这样),则标记和klass都是本地机器单词。对于数组,间隙总是存在于LP64系统上,而只存在于ILP32系统中具有64位元素的数组上。 如果UseCompressedOops为真,则klass为32位。非数组在klass之后有一个间隙字段,而数组在klass之后存储长度字段。
对于对象的大小计算“头+属性+引用”是不正确的。首先,对对象的引用不是引用对象大小的一部分。可以有任意数量的对同一对象的引用,但这些引用根本不必在堆内存或RAM中,因为优化的代码可能纯粹通过CPU寄存器访问对象。
此外,正如上面引号中所暗示的那样,有一些对齐规则使得字段所需内存的计算变得非常重要。如果存在适合于实例字段的字段,则头中可能会出现一个空白,用于存储实例字段。虽然同一类的字段可能被安排为最小化填充,但子类必须与超类的布局共存,可能会向其添加更多字段,并且只有在具有拟合类型字段的情况下才能填补空白,否则,由于类层次结构的原因,可能会有更多的空白。
对于数组,您可以从引用的文章中派生出32位HotSpot表示使用12字节的头,除非类型是long[]或double[],在这种情况下为16字节。
对于64位实现,UseCompressedOops选项(默认情况下是打开的)允许将64位标记字与32位klass和32位长度组合为16字节的头。只有当UseCompressedOops关闭时,报头才会是24个字节。
发布于 2018-05-24 11:45:26
您可以使用由全能的Aleksey编写的JOL框架进行测试。
使用它实际上非常容易,首先让我们定义您所关心的布局:
Layouter layout32Bits = new HotSpotLayouter(new X86_32_DataModel());
Layouter layout64Bits = new HotSpotLayouter(new X86_64_DataModel());
Layouter layout64BitsComp = new HotSpotLayouter(new X86_64_COOPS_DataModel());然后,让我们定义一个数组并查看结果:
int [] ints = new int[1];
System.out.println(ClassLayout.parseInstance(ints, layout32Bits).toPrintable());
System.out.println(ClassLayout.parseInstance(ints, layout64Bits).toPrintable());
System.out.println(ClassLayout.parseInstance(ints, layout64BitsComp).toPrintable());让我们一次跑一次。对于32bits VM
[I object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 09 00 00 00 (00001001 00000000 00000000 00000000) (9)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 10 0b 40 29 (00010000 00001011 01000000 00101001) (692062992)
12 40 int [I.<elements> N/A
52 12 (loss due to the next object alignment)
Instance size: 64 bytes
Space losses: 0 bytes internal + 12 bytes external = 12 bytes total因此,您获得了头部的12 bytes,(两个标头的4+4,加上数组大小的4,它是一个int);然后得到数组将容纳的10个it的40字节。
其次,我不太确定我是否理解。到目前为止,我们有52字节,对象在8 bytes上对齐,这意味着这52个值应该四舍五入到56 bytes,以使其对齐到8。
相反,它说的是12 bytes loss due to the next object alignment。我只能猜测可能有两件事,请先阅读这里的评论或可能有些领域只是为了内部的目的。
不打算在这里显示其余的示例输出(您也可以这样做),我将问一个后续的问题,事情是不清楚的事情,我不清楚的填充很快。
https://stackoverflow.com/questions/50502663
复制相似问题