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. 确切的堆栈跟踪将像这样,它由包含“prev”属性的实际指令组成,该属性将是已被调用以加载该变量的方法:

被检元素样本

问题是我们有所有者属性,名称属性,但我无法获得对该对象的引用。在以下情况下:

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 回答