【问题标题】:Java primitive array layout in memory内存中的 Java 原始数组布局
【发布时间】:2018-05-24 12:12:05
【问题描述】:

这是我想提出问题的两个示例(假设您在这里有JOL):

Layouter layout32Bits =  new HotSpotLayouter(new X86_32_DataModel());
Layouter layout64BitsComp = new HotSpotLayouter(new X86_64_COOPS_DataModel());

还有一个使用这个的例子:

int [] ints = new int[10];  

System.out.println(ClassLayout.parseInstance(ints, layout32Bits).toPrintable());
System.out.println(ClassLayout.parseInstance(ints, layout64BitsComp).toPrintable());

这是两个输出:

  [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 1b 0c 1a (00010000 00011011 00001100 00011010) (437000976)
 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

  [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 1b 0c 1a (00010000 00011011 00001100 00011010) (437000976)
 12     4        (object header)     01 00 00 00 (00000001 00000000 00000000 00000000) (1)
 16    40    int [I.<elements>            N/A
 56     8        (loss due to the next object alignment)
 Instance size: 64 bytes
 Space losses: 0 bytes internal + 8 bytes external = 8 bytes total

我主要了解输出,我不明白的是这些是什么:

12 bytes external and 8 bytes external

一般来说,对象是8 bytes 对齐的,那么为什么需要添加比需要更多 的填充?

我知道一些奇怪的事情,the first one has to do with the API that JOL is using 和第二个has to do with internal data, that needs to be hidden

我也知道this,但它似乎无关,因为它意味着内部填充

有人可以解释一下吗?

【问题讨论】:

  • Aren't alignments always a power of 2? 在这两种情况下,大小都大于 32 个字节,因此您需要最多填充 64 个字节。但不确定这是否适用于此...
  • FWIW,我得到了 56 字节的实例大小,由于 32 位中的下一个对象对齐而丢失了 4 个,在 64 位中丢失了 0 个。
  • @Michael 指出它确实不是必须是二的幂,对吧?我正在研究一个例子来向 JornVernee 证明这一点
  • 如果你在对象头的某处看不到数组长度,你就知道有问题了……
  • @Holger :) 哦,天哪!甚至没有注意到,真是个白痴……谢谢!

标签: java arrays jvm jvm-hotspot jol


【解决方案1】:

Instance size: 64 bytes 是针对当前 VM 配置计算的,但您明确指定了不同的(不兼容的)Layouter

实际尺寸(用Instrumentation.getObjectSize计算)与预期尺寸(用Layouter计算)之间的差异将被视为loss due to the next object alignment

ClassLayout.java

【讨论】:

  • 还有一个小问题,显式布局器不应该仍然填充到 8 字节对齐吗?
  • @Eugene 我不确定你的意思。 VM 告诉“这个对象当前在堆中占用了 64 个字节”,而 Layouter 试图解释这 64 个字节的来源。当您从不同的 VM 配置中选择 Layouter 时,您肯定会得到令人困惑的结果,因为它无法合理地解释额外的字节。我不知道为什么在 JOL 中可以实例化任意 Layouter - 可能这是一个 API 错误。
  • 我根本不认为这是一个错误;如果我想在没有访问特定平台的情况下找到对象的布局怎么办?喜欢x86_32?我真正的意思是显式布局计算大小为52 bytes,我真的期待稍后说:4 bytes padding - instance size = 56 bytes 而不是给我 real 大小。我并没有要求真正的平台大小开始。或者换一种说法:对于第一个示例,real x86_32 位的结果是什么?
  • @Eugene 好的。我看到的是 ClassLayout 采用为当前运行的 VM 计算的实例的实际大小,而不考虑给定布局器的数据模型。无论如何,在我看来,这似乎是不一致的。我建议针对 JOL 提出问题。
  • 我最初是想要的,所以感谢您确认
猜你喜欢
  • 2019-09-03
  • 1970-01-01
  • 2010-10-03
  • 2010-12-15
  • 2013-01-13
  • 2021-08-28
  • 2023-04-09
相关资源
最近更新 更多