嘲弄JVM的压缩哎呀

所以我理解现在默认情况下在HotSpot VM中启用了压缩的oops。 从Java SE 6u23开始,它通过VM选项-XX:+UseCompressedOops支持此-XX:+UseCompressedOops 。 我知道它允许有效的CPU缓存利用率,因为CPU缓存可以容纳更多数量的引用,而不是它们必须处理64位大小的引用。 但我不明白的是,如何只使用32位JVM可以处理多达2 64个地址。

为了简化问题,我们如何仅使用2位来处理最多2个4个存储器地址? 这种地址方案可能的编码/解码是什么?

有关压缩oops的详细说明,请参阅John Rose @ Oracle 中的“Hotspot JVM中的压缩oops”一文。

TL; DR版本是:

  • 在现代计算机体系结构中,内存地址是字节地址,
  • Java对象引用是指向单词1开头的地址,
  • 在64位机器上,字对齐意味着对象引用/地址的底部3位为零2
  • 因此,通过将地址向右移3位,我们可以将64位地址的35位“压缩”为32位字,
  • 并且,可以通过将3位向左移位来完成解压缩,这将3个零位置回,
  • 35位寻址允许我们使用在64位计算机上适合32位(半)字的压缩oops来表示最多32 GB堆内存的对象指针。

请注意,这适用于64位JVM。 我们仍然需要能够处理包含(最多)32 GB堆1的内存,这意味着64位硬件地址(在现代CPU /计算机体系结构上)。

另请注意,这样做会受到轻微的惩罚; 即在常规和压缩引用之间转换所需的转换指令。 然而,另一方面是消耗的实际内存较少3 ,因此内存缓存通常更有效。

1 – 这是因为现代计算机体系结构针对字对齐的内存访问进行了优化。

2 – 这假设您没有使用-XX:ObjectAlignmentInBytes来将对齐方式从其默认(和最小)值8字节增加。

3 – 事实上,内存节省是特定于应用程序的。 它取决于平均对象对齐浪费,参考与非参考字段的比率等。 如果考虑调整对象对齐,它会变得更复杂。


为了简化问题,我们如何仅使用2位来处理多达2个4个存储器地址? 这种地址方案可能的编码/解码是什么?

您不能寻址2个4字节地址。 但是,您可以使用2位字地址寻址2 2个字地址(假设32位字)。 如果您可以假设所有字节地址都是字对齐的,那么您可以将4位字节地址压缩为2位字地址,方法是将其移位2位。

它不适用于32位JVM。 这是为了减轻64位JVM中发生的额外开销。 我认为Oracle的页面解释得很好:

压缩的哎呀

压缩的oops表示托管指针(在JVM软件中的许多但不是所有位置)作为来自64位Java堆基址的32位对象偏移量。 因为它们是对象偏移而不是字节偏移,所以它们可以用于处理多达40亿个对象(不是字节),或者堆大小最多大约32千兆字节。 要使用它们,必须将它们缩放8倍并添加到Java堆基址以查找它们引用的对象。

资源

CompressedOops 。

从文章:并非所有指针都被压缩,压缩的指针是32位值,必须按8倍缩放,并添加到64位基址以查找它们引用的对象。

现在请注意,使用这些32位指针无法处理2 ^ 64位内存,但您可以使用它们访问大量Objects 。 如果在内存位置x有一个对象,则无法在x+1处拥有另一个对象。 这就是您不需要访问每个内存位置的原因。