java - 如何获取ASM中的引用?

标签 java bytecode java-bytecode-asm bytecode-manipulation jvm-bytecode

总结:使用 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”属性的实际指令组成,该属性将是被调用来加载该变量的方法:

Sample of inspected element

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

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

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

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

我应该如何实现这个目标?

最佳答案

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

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

关于java - 如何获取ASM中的引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38169742/

相关文章:

java - 如何正确获取另一个城市的当前时间?

java - 如何在 ActiveMQ 中创建队列?

java - Log4j Logger 中的晦涩字段和修饰符

java - 关于java如何执行字节码有很好的引用吗?

Java ASM 字节码 - 查找属于特定方法调用的所有指令

java - Hibernate:实体关系和额外表

c# - 是否存在强制对 OR 条件语句中的两个表达式求值的模式或技巧?

java - Java如何将字符串编码成字节码?

java - ClassNode.accept 上的 NullPointerException