我写了一个简单的Java字节码解析器来进行一些实验,最近它在一个意想不到的地方失败了。当读取Java 1.1.8.16的rt.jar
中的java/lang/reflect/Member.java
时,我的解析器发疯了,因为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
标志。接口不能是final;如果是,则其实现永远无法完成(§2.13.1),因此不能设置其ACC_FINAL
标志。JVM规范的第9版也有类似的说法:
如果设置了
ACC_INTERFACE
标志,则必须同时设置ACC_ABSTRACT
标志,并且不得设置ACC_FINAL
、ACC_SUPER
、ACC_ENUM
和ACC_MODULE
标志。Oracle/Sun JVM是否执行此“必须”要求?如果是,从何时开始?如果不是,为什么JVM规范会假装它是必需的?