java - 为什么 long 和 double 在 Java 类的常量池中占用两个条目?

标签 java jvm constants .class-file

Java Virtual Machine Specification声明 8 字节(例如 longdouble)常量占用 constant_pool 表中的两个条目,不像其他常量只占用每一个条目。该规范还提到这是一个糟糕的选择,但没有解释原因。

这个设计决定背后的最初原因是什么?当时的好处是什么?

最佳答案

明确的答案需要与参与 Java 早期开发的人员交谈。但是,我认为很明显,字节码格式最初设计时考虑的是朴素解释器的性能。

考虑如何编写一个非常简单的 Java 字节码解释器。没有 JIT,没有优化等。您只需执行每条指令即可。假设常量池在加载时已被解码为 32 位值的表,像 ldc2_w x 这样引用常量池的指令将按照以下行执行 C 代码

*(*int64)(stack_ptr += 8) = *(*int64)(constant_pool_ptr + x * 4)

基本上,如果您在 32 位机器上,并且正在将所有内容转换为未经优化的原始指针访问,那么为 64 位值使用两个槽是实现事情的简单逻辑方法。

今天它是一个糟糕的选择的原因是因为现在,口译员并不是像这样完全没有优化。事实上,代码通常是 JITed 的。此外,64 位平台是常态,这意味着引用类型无论如何都占用 64 位*,即使规范将它们视为 32 位值。因此,这种 hack 不再有任何好处,但我们仍然付出了规范和实现复杂性的代价。

^ 至少理论上是这样。 JVM 默认使用 32 位压缩指针,即使在 64 位平台上也是如此,以减少内存使用。

关于java - 为什么 long 和 double 在 Java 类的常量池中占用两个条目?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40059321/

相关文章:

java - 如何检查计数器是否越界

java - Java 中的内存效率

caching - 当我使用略多于 64kb 的常量缓存时,为什么我的内核不会失败? (OpenCL/CUDA)

c++ - 将 const char * const 参数的成员分配给新值

java - 在 while(rset.next) 内调用方法时耗尽结果集

java - 在Android中更改 "Settings"的名称

java - 如何修复 Firebase 身份验证中的空指针异常?

Scala 在编译时获取函数调用的行和文件

java - 禁用 AdaptiveSizePolicy 时的并行垃圾收集器问题

java - 会记住它的值的计数器