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コンパイラは機能するので、明らかに私の理解は間違っています...
誰かが私のためにこれを明確にすることができますか? クラスをロードし、フィールド参照を探し、それが見つからない場合は、見つかるまでクラス階層の作業を開始する必要がありますか?
これを行うための正しい動作が記述されている仕様へのポインタは大歓迎です...