JVM压缩的Oops背后的技巧
所以我明白压缩的oops现在在HotSpot VM中默认启用。从Java SE 6u23开始,它通过VM选项对此表示支持。我知道它允许高效的CPU缓存利用率,因为CPU缓存可以容纳比必须处理64位大小的引用更多的引用。但我不明白的是,仅使用32位JVM如何寻址多达2个64个地址。-XX:+UseCompressedOops
为了简化问题,我们如何仅使用2位即可解决多达2个4内存地址?这种地址方案的可能编码/解码是什么?
所以我明白压缩的oops现在在HotSpot VM中默认启用。从Java SE 6u23开始,它通过VM选项对此表示支持。我知道它允许高效的CPU缓存利用率,因为CPU缓存可以容纳比必须处理64位大小的引用更多的引用。但我不明白的是,仅使用32位JVM如何寻址多达2个64个地址。-XX:+UseCompressedOops
为了简化问题,我们如何仅使用2位即可解决多达2个4内存地址?这种地址方案的可能编码/解码是什么?
有关压缩 oops 的详细说明,请参阅 John Rose @ Oracle 的“Hotspot JVM 中的 Compressed oops”一文。
TL;DR 版本是:
请注意,这仅适用于 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 GB。要使用它们,必须将它们缩放 8 倍并添加到 Java 堆基址以查找它们引用的对象。