我在 Java 字节码规范中发现了一些我不理解的东西。
考虑以下类层次结构:
class FilterOutputStream {
protected OutputStream out;
}
class PrintStream extends FilterOutputStream {
public void write(...) {
out.write(...);
}
}
用 javap 查看 PrintStream 的字节码,我看到读取out
字段是这样完成的:
getfield #21
正如预期的那样,参考#21 是一个字段参考,包含该字段的类、名称和描述符。但是,它看起来像这样:
const #21 = Field #30.#204; // java/io/PrintStream.out:Ljava/io/OutputStream;
这真是令人费解,因为这表明该out
字段是 PrintStream 的成员。这不是真的; 它是FilterOutputStream 的成员,这是我希望在上面的字段参考中看到的类。JVM 规范非常模糊,但似乎支持我:
class_index 项的值必须是 constant_pool 表的有效索引。该索引处的 constant_pool 条目必须是 CONSTANT_Class_info(第 4.4.1 节)结构,表示具有字段或方法作为成员的类或接口类型。
(来自http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.4.2。)
这对我来说是个问题,因为我查看字段引用,加载类,然后找不到字段。另一方面,Java 编译器确实可以工作,所以我的理解显然是错误的......
有人可以为我澄清一下吗?我是否应该加载类,查找字段引用,如果找不到,则开始处理类层次结构,直到找到它?
指向规范的指针,指向它描述这样做的正确行为的地方将不胜感激......