为什么 CONSTANT_Long_info 和 CONSTANT_Double_info 仍然是 2 个条目?

Why are CONSTANT_Long_info and CONSTANT_Double_info still 2 entires?

最初设计JVM的时候,设计者让常量池中的CONSTANT_Long_infoCONSTANT_Double_info结构占用了2个entry(据说是因为这样可以索引常量池4个-字节对齐或类似的东西)。

但是,根据JVM 10 specification, that has not been changed

如果更改它需要更改大量代码,这是有意义的,因为 JVM 应该能够 运行 为旧 JVM 构建的代码,但在我看来,它需要非常对条件进行一些更改以确定您是否正在处理来自早期版本的 class - 唯一相关的时间是您是否正在初始化常量池或是否正在迭代它,这不会' t 经常发生并且无论如何都充满了条件。

此外,过去引入了 Java9 个模块等更大的突破性变化。那么,为什么今天还是那样呢?是否有架构方面的原因,或者到目前为止不值得任何人花时间?

与从 Java 1.1 到 Java 11 的大多数更改一样,模块的引入在字节码格式方面没有太大变化。当涉及到应用程序逻辑或反射时,它可能是激进的,而不是字节码处理工具,它只需要轻微的扩展。

改变 CONSTANT_Long_infoCONSTANT_Double_info 的逻辑只有在你追求更大的图景时才有意义,例如还改变了 longdouble 采用两个局部变量和两个操作数堆栈条目的事实。然后,你将不得不接触很多代码地方。

但不管变化有多大,重要的问题是,你换来了什么?更好的感觉不算数。改变它的主要原因是为了简化规则,从而简化字节码处理工具。但是,由于这些工具需要条件来启用对旧 class 文件的处理,因此这种优势不会实现。事实上,随着这样的改变,工具会变得更加复杂。

当您开发一种无论如何都需要新工具的全新格式时,情况会有所不同,例如它本来是 JMOD 格式的一个选项,但开发新工具链的需要正是它没有发生的原因,当前的 JMOD 只是一个 zip 文件,就像旧的 jar 文件一样。

一个反例是 the StackMapTable attribute,它在开发时没有向后兼容性约束,因此不计算 longdouble 条目两次。处理工具的职责是将这些堆栈映射条目转换为堆栈帧条目,这些条目确实使用两个 longdouble 值(除非我们正在谈论以另一种方式进行转换的环境圆)。