我编写了一个简单的 Java 字节码解析器来做一些实验,最近它在一个意想不到的地方失败了。java/lang/reflect/Member.java
从 Java 1.1.8.16读取时rt.jar
,我的解析器发疯了,因为Member
开始时是这样的(注意缺少的ACC_ABSTRACT
标志):
Classfile Member.class
Last modified Aug 8, 2002; size 350 bytes
MD5 checksum 9a1aaec8e70e9a2ff9d63331cb0ea34e
Compiled from "Member.java"
public interface java.lang.reflect.Member
minor version: 3
major version: 45
flags: (0x0201) ACC_PUBLIC, ACC_INTERFACE
...
Java 1.2.2.17 的版本更正了这一点,并将标志设置为0x0601
( ACC_ABSTRACT | ACC_INTERFACE | ACC_PUBLIC
)。
我能找到的最早的 JVM 规范(据称是 1.0.2)有这样的说法(§4.1,第 86 页,强调添加):
接口是隐式抽象的(§2.13.1);它
ACC_ABSTRACT
的标志必须被设置。接口不能是最终的;如果是这样,它的实现将永远无法完成(第 2.13.1 节),因此它不能ACC_FINAL
设置其标志。
JVM 规范的第 9 版有类似的话要说:
如果设置了标志
ACC_INTERFACE
,则ACC_ABSTRACT
标志也必须设置,并且不能设置ACC_FINAL
、ACC_SUPER
、ACC_ENUM
和ACC_MODULE
标志集。
Oracle/Sun JVM 是否强制执行“必须”这样的要求?如果有,从什么时候开始?如果不是,为什么 JVM 规范还要假装它是必需的?