为什么 Java 对象必须是 8 的倍数?

2022-09-02 10:11:05

我知道Java使用填充;对象必须是 8 个字节的倍数。但是,我看不出它的目的是什么。它的用途是什么?它的主要目的究竟是什么?


答案 1

其目的是对齐,这允许以一些空间为代价更快地访问内存。如果数据未对齐,则处理器需要执行一些移位才能在加载内存后访问它。

此外,垃圾回收被简化(并加速)最小分配单元的大小。

Java不太可能有8个字节的要求(除了在64位系统上),但是由于32位架构在Java创建时是常态,因此Java标准中可能需要4字节对齐。


答案 2

接受的答案是推测(但部分正确)。这是真正的答案。

首先,@U2EF1,8字节边界的好处之一是8字节是大多数处理器上的最佳访问。然而,该决定远不止于此。

如果您有32位引用,则可以寻址多达2 ^ 32或4 GB的内存(实际上您获得的内存更少,更像是3.5 GB)。如果您有 64 位引用,则可以对 2^64(内存的 TERRABYTE 数)进行寻址。但是,对于 64 位引用,所有内容往往会减慢速度并占用更多空间。这是由于处理 64 位的 32 位处理器会产生开销,并且在所有处理器上,由于空间更少和垃圾回收更多,因此 GC 周期更多。

因此,创建者采取了中间立场,并决定使用35位引用,它允许高达2 ^ 35或32 GB的内存并占用更少的空间,因此具有与32位引用相同的性能优势。这是通过获取32位参考并在读取时将其向左移3位,并在存储引用时将其向右移3位来完成的。这意味着所有对象必须在 2^3 边界(8 个字节)上对齐。这些称为压缩的普通对象指针或压缩的oops。

为什么不使用 36 位引用来访问 64 GB 内存?嗯,这是一个权衡。16 字节对齐需要大量浪费空间,据我所知,与 8 字节对齐相比,绝大多数处理器都不会从 16 字节对齐中获得速度优势。

请注意,JVM 不会打扰使用压缩的 oops,除非最大内存设置为高于 4 GB,默认情况下不会这样做。您实际上可以使用标志启用它们。-XX:+UsedCompressedOops

这可以追溯到 32 位 VM 在 64 位系统上提供额外的可用内存的时代。据我所知,64 位 VM 没有限制。

来源:Java 性能:权威指南,第 8 章