2

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コンパイラは機能するので、明らかに私の理解は間違っています...

誰かが私のためにこれを明確にすることができますか? クラスをロードし、フィールド参照を探し、それが見つからない場合は、見つかるまでクラス階層の作業を開始する必要がありますか?

これを行うための正しい動作が記述されている仕様へのポインタは大歓迎です...

4

1 に答える 1

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.
于 2013-10-08T00:53:42.013 に答える