20

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

4

3 回答 3

19

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

此外,最小分配单元的大小越大,垃圾收集就越简单(并加速)。

Java 不太可能要求 8 字节(64 位系统除外),但由于 32 位体系结构是创建 Java 时的标准,因此 Java 标准可能需要 4 字节对齐。

于 2012-08-12T22:43:49.290 回答
8

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

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

如果您有 32 位引用,则最多可以寻址 2^32 或 4 GB 的内存(实际上您得到的内存更少,更像 3.5 GB)。如果您有 64 位引用,则可以寻址 2^64,即 TB 的内存。但是,使用 64 位引用时,一切都会变慢并占用更多空间。这是由于 32 位处理器处理 64 位的开销,并且在所有处理器上,由于更少的空间和更多的垃圾收集,更多的 GC 周期。

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

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

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

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

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

于 2015-04-08T20:29:16.900 回答
-2

Java 中的数据类型大小是 8(不是字节)的倍数,因为大多数现代处理器中的字大小是 8 位的倍数:16 位、32 位、64 位。通过这种方式,可以使对象中的字段适合(“对齐”)一个或多个单词并浪费尽可能少的空间,利用底层处理器的指令来操作字大小的数据。

于 2012-08-12T22:42:35.460 回答