What is Compressed Class Space? - tenji/ks GitHub Wiki

What is Compressed Class Space?

本系列的前一篇文章,Metaspace Architecture 故意遗漏了 Compressed Class Space。这进一步使情况复杂化。

让我们来谈谈它。

在 64 位平台上,Hotspot 使用被称为 Compressed Object Pointers (“CompressedOops”) 和 Compressed Class Pointers 的优化技术。两者都是同一事物的变体。

压缩指针是一种引用数据的方式 - Java 堆中的对象或 Metaspace 中的类元数据 - 即使在 64 位平台上也使用 32 位引用。

这有许多优点,例如更小的指针大小会减少内存占用和更好地使用缓存,并且在某些平台上可以使用更多的寄存器。

注意:可以在此处找到对 Compressed Object Pointers 的一个很好的解释:JVM Anatomy Quark #23: Compressed References

此外,类似的动机推动了 Linux x32 abi

由于最终需要一个 64 位地址来访问那个东西,那个 32 位“指针”实际上是一个偏移量 - 可能被位移 - 到具有已知公共基数的区域中。

关于 Metaspace,我们不关心 compressed oops 但必须处理压缩的类指针:

每个 Java 对象在其 header 都有一个对位于 Metaspace 中 Java 堆之外的本机结构的引用:Klass 结构。

使用压缩类指针时,该引用是一个 32 位值。为了找到该结构的真实 64 位地址,我们为其添加了一个已知的公共基址,并且可能还将该值左移三位:

该技术对分配这些 Klass 结构的位置设置了技术限制:

Klass 结构的每个可能位置都必须在 4G(非移位模式)|32G(移位模式)的范围内,才能通过与公共基址的 32 位偏移量到达。

这两个限制意味着我们需要将 Metaspace 分配为一个连续的区域。

当通过系统 API(如 malloc(3) 或 mmap(3))从系统分配内存时,地址由系统选择并且可以是适合类型范围的任何值。因此,在 64 位平台上,当然不能保证后续分配会产生范围限制内的地址。例如,一个 mmap(3) 调用可以映射在 0x0000000700000000,另外一个在 0x0000000f00000000。

因此,我们必须使用单个 mmap() 调用来为 Klass 对象建立区域。所以我们需要预先知道这个区域的大小,它不能大于 32G。

参考链接