1

現在、ASM を使用してターゲット アプリケーションのフィールド値を変更しようとするすべての試みをインターセプトしていますが、これは期待どおりに機能しています。ASM を使用すると、メソッドまたはコンストラクタ コード セグメントの先頭または末尾に命令を追加できるからです。

ただし、たとえば、メソッドまたはコンストラクターのスコープ外のフィールドを初期化するのは、かなり一般的な開発者パラダイムであることがわかりました。

public class Example{

  //--VARIABLE INITIALIZATION OUTSIDE METHOD OR CONSTRUCTOR SCOPE ---
  private String aString = "A String Value";

  //zero argument constructor
  public Example(){

  }

  //all other methods.


}

私の質問は、この方法で行われたフィールドアクセスをインターセプトするタスク、つまりメソッドまたはコンストラクターのコンテキストの外でどのようにアプローチするのでしょうか?

4

2 に答える 2

2

これは、ソースコードのコンストラクターの外にあるように見えますが、実際には、バイトコードでは、初期化子はすべてコンストラクターの一部であり、コンパイラーによってコンストラクターに「移動」されます。初期化子は、暗黙的または明示的な呼び出しの、コンストラクターの残りのコードの前に配置されます。特に、これは、次のような状況が発生した場合に発生します。super()

class Super {
  protected Super() {
    doSomeStuff();
  }

  protected abstract void doSomeStuff();
}

class Sub extends Super {
  private int number = 1;

  public Sub() {
    super();
    System.out.println("in Sub(): " + number);
  }

  protected doSomeStuff() {
    System.out.println("in doSomeStuff(): " + number);
  }
}

その後、new Sub();印刷します

in doSomeStuff(): 0
in Sub(): 1

フィールド初期化子が実行される前にin doSomeStuff印刷が行われるため。Sub

于 2012-12-29T15:41:43.530 に答える
1

すべてのコードはメソッド内にあります (コンストラクターと静的初期化子もメソッドです)。

フィールド宣言で確認できるフィールドの初期値がありますが、コンパイラはこれらをあまり使用していないようです。

private String aString = "A String Value";

//zero argument constructor
public Example(){

}

と同じです

private String aString;

//zero argument constructor
public Example(){
    super();
    aString = "A String Value";
}
于 2012-12-29T15:40:48.687 に答える