如何在 ASM 中获取引用?

How to get references in ASM?

总结:使用 ASM,给定字节码 class,对于每个方法指令 (MethodInsnNode),我需要获取正在使用的引用。

考虑以下 class:

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;)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" 属性的实际指令组成,该属性将成为加载该变量时调用的方法:

问题是我们有 owner 属性、name 属性,但我无法获得对该对象的引用。在以下情况下:

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

我需要对 ASM 中的 "cemo" 对象的引用。

到目前为止我尝试过的: - 获取框架对象,但它只包含变量 "slots",没有引用它。 - 分析 MethodInsnNode 之前的说明。

我该如何完成?

JVM 是一个堆栈机器,即方法总是在操作数堆栈的顶部值上调用,其中 this 引用是非静态方法的第一个隐式参数。为了执行您的计划,您需要随时跟踪操作数堆栈上的所有参数,然后在处理字节代码中的方法调用后确定当前为 this 填充的值。

这意味着您需要处理方法的任何指令并跟踪任何寄存器和栈槽当前引用的对象。以有限的方式,这允许您跟踪调用方法的实例。但是请注意,Java(字节码)程序可能非常复杂,因为它们强加了 Java 编程语言以外的其他限制,并允许在代码中任意跳转。基本上,为了了解某个方法在任何时间点的作用,您需要模拟一般情况下的方法调用,因此您需要设置一些相当困难的东西。