コード:
public class Foo {
public byte[] bar = new byte[3];
}
コンパイルすると次のようになります:
class Foo2 {
public byte[] bar;
public Foo2() {
this.bar = new byte[3];
}
}
ここには「リテラル」はありません。フィールド初期化子と初期化子ブロックは、すべてのコンストラクターのコードの前に (ソース コードの順序であると思います) 追加されるだけです。探している情報は保持されません。これらのコンストラクターの逆コンパイルされたコードを見て、何らかの方法で分析する必要がありますが、それはあいまいです。
このコンストラクターのオペコードは次のとおりです。
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: aload_0
5: iconst_3
6: newarray byte
8: putfield #2; //Field bar:[B
11: return
インデックス 4 ~ 8 は行 に対応しますthis.bar = new byte[3];
。彼らは大まかに意味します:
this
参照をスタックにプッシュします。
- 整数
3
をスタックにプッシュします。
- 整数 (
3
) をスタックの一番上にポップし、その長さのバイト配列を作成し、その配列をスタックにプッシュします。
bar
スタック (バイト配列) の一番上にある値を、スタック ( ) の上から 2 番目にあるオブジェクトのフィールド #2 (つまり ) の値として設定しますthis
。(また、2 つをスタックからポップします。)
これは、元の Java ソースにうまく対応していません。ご覧のとおり、「this.bar = …」を実装する部分の途中に「new byte[3]」に相当する部分が挿入されており、これだけの単純な式でも順番が狂っています。バイトコードからステートメントを再構築することはおそらく簡単ではありません – それらは明示的に区切られていません.スタックからすべてをポップするとステートメントは終了します.