2013-10-08 67 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_變化。接口上的字段?這是錯誤的......) –