2013-10-08 41 views
1

我在Java字节码规范中发现了一些我不明白的东西。Java字节码中的字段引用

考虑下面的类层次结构:

class FilterOutputStream { 
    protected OutputStream out; 
} 

class PrintStream extends FilterOutputStream { 
    public void write(...) { 
    out.write(...); 
    } 
} 

纵观字节码的PrintStream与javap的,我看到在读了out场像这样做:

getfield #21 

参考#21,如预期的那样,Field引用包含该字段的类,名称和描述符。然而,它看起来像这样:

const #21 = Field #30.#204; // java/io/PrintStream.out:Ljava/io/OutputStream; 

这实在令人费解,因为这表示,out场是PrintStream的一员。这不是真的;它是FilterOutputStream的成员,这是我期望在上面的字段引用中看到的类。 JVM规范相当模糊,但似乎支持我:

class_index项的值必须是常量池表中的有效索引。 该索引处的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编译器可以工作,所以显然我的理解是错误的...

有人可以为我澄清一下吗?我是否应该加载这个类,寻找字段引用,如果没有找到,那么直到找到它时才开始处理类层次结构?

指针到规范的地方它描述了这样做的正确的行为,将不胜感激......

回答

2

你错过了JVM规范,在那里谈场查找的一部分。如果该字段在当前类中不存在,则开始搜索超类和接口。

5.4.3.2 Field Resolution 
To resolve an unresolved symbolic reference from D to a field in a class or interface 
C, the symbolic reference to C given by the field reference must first be resolved 
(§5.4.3.1). Therefore, any exception that can be thrown as a result of failure of 
resolution of a class or interface reference can be thrown as a result of field 
resolution. If the reference to C can be successfully resolved, an exception relating 
to the failure of resolution of the field reference itself can be thrown. 
When resolving a field reference, field resolution first attempts to look up the 
referenced field in C and its superclasses: 
1. If C declares a field with the name and descriptor specified by the field 
reference, field lookup succeeds. The declared field is the result of the field 
lookup. 
2. Otherwise, field lookup is applied recursively to the direct superinterfaces of 
the specified class or interface C. 
3. Otherwise, if C has a superclass S, field lookup is applied recursively to S. 
4. Otherwise, field lookup fails. 
+0

谢谢!正是我在找什么。 (自从上一次我做了关于字节码的详细工作后,这实际上已经发生了_changed_变化。接口上的字段?这是错误的......) –