0

要約: ASM を使用して、特定のバイトコード クラスで、メソッド命令 ( MethodInsnNode ) ごとに、使用されている参照を取得する必要があります。

次のクラスを検討してください。

public void myMethod(){
String str1 = "str12";
String str2 = str1;
String str3 = "str3";
Boolean myBool = true;
Boolean myBool2 = true;
Cemo cemo = new Cemo();
assertTrue(cemo.isTrue());

assertTrue(cemo.isTrue());

}

次の生成されたバイトコード命令を考慮してください。

Code:
   0: aload_0
   1: invokespecial #1                  // Method java/lang/Object."<init>":()V
   4: return



public void myMethod();
    Code:
       0: ldc           #2                  // String str12
       2: astore_1
       3: aload_1
       4: astore_2
       5: ldc           #3                  // String str3
       7: astore_3
       8: iconst_1
       9: invokestatic  #4                  // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean;
      12: astore        4
      14: iconst_1
      15: invokestatic  #4                  // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean;
      18: astore        5
      20: new           #5                  // class com/devfactory/utqg/analysis/InstrumentationClass$Cemo
      23: dup
      24: aconst_null
      25: invokespecial #6                  // Method com/devfactory/utqg/analysis/InstrumentationClass$Cemo."<init>":(Lcom/devfactory/utqg/analysis/InstrumentationClass$1;)V
      28: astore        6
      30: aload_0
      31: aload         6
      33: invokevirtual #7                  // Method com/d/utqg/analysis/InstrumentationClass$Cemo.isTrue:()Z
      36: invokestatic  #4                  // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean;
      39: invokespecial #8                  // Method assertTrue:(Ljava/lang/Boolean;)V
      42: aload_0
      43: aload         6
      45: invokevirtual #7                  // Method com/d/utqg/analysis/InstrumentationClass$Cemo.isTrue:()Z
      48: invokestatic  #4                  // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean;
      51: invokespecial #8                  // Method assertTrue:(Ljava/lang/Boolean;)V
      54: return
}

ASM を使用して呼び出されているオブジェクト参照を取得する方法を見つけようとしています。バイトコード レベルでは、INVOKESPECIAL命令が呼び出されるたびに、以前に使用される値がロードされます。例えば:

 31: aload         6     //Loading the value stored in 6 position
      33: invokevirtual #7                  // Method com/d/utqg/analysis/InstrumentationClass$Cemo.isTrue:()Z

ですから、そこへの参照があります。しかし、ASM では、への参照はありませんthis。正確なスタックトレースは次のようになります。これは、その変数をロードするために呼び出されたメソッドである「前の」属性を含む実際の命令によって構成されています。

検査要素のサンプル

問題は、所有者属性、名前属性があることですが、そのオブジェクトへの参照を取得できません。次の場合:

Boolean myBool2 = true;
Cemo cemo = new Cemo();
assertTrue(cemo.isTrue());

ASM の「cemo」オブジェクトへの参照が必要です。

これまでに試したこと: - フレーム オブジェクトを取得しますが、変数「スロット」のみが含まれ、参照は含まれません。MethodInsnNode-前の指示を分析します。

どうすればこれを達成できますか?

4

1 に答える 1

5

JVM はスタック マシンです。つまり、メソッドは常にオペランド スタックの一番上の値で呼び出されます。this参照は非静的メソッドの最初の暗黙の引数です。計画を実行するには、オペランド スタック上のすべての引数をいつでも追跡してthis、バイト コードでメソッド呼び出しを処理した後、現在どの値が入力されているかを判断する必要があります。

これは、メソッドのすべての命令を処理し、レジスタとスタック スロットが現在参照しているオブジェクトを追跡する必要があることを意味します。これにより、限定的な方法で、メソッドが呼び出されたインスタンスを追跡できます。ただし、Java (バイトコード) プログラムは、Java プログラミング言語以外の制限を課し、コード内の任意のジャンプを許可するため、非常に複雑になる可能性があることに注意してください。基本的に、ある時点でメソッドが何をするかを知るには、一般的なケースのメソッド呼び出しをエミュレートする必要があるため、かなり難しい設定を行う必要があります。

于 2016-07-04T08:18:19.863 に答える