Ser*_*ras 0 java bytecode bytecode-manipulation java-bytecode-asm 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());
Run Code Online (Sandbox Code Playgroud)
}
考虑以下生成的字节码指令:
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
}
Run Code Online (Sandbox Code Playgroud)
我试图找出一种如何获取使用 ASM 调用的对象引用的方法。在字节码级别,每次INVOKESPECIAL调用指令时,它都会加载之前将使用的值。例如:
31: aload 6 //Loading the value stored in 6 position
33: invokevirtual #7 // Method com/d/utqg/analysis/InstrumentationClass$Cemo.isTrue:()Z
Run Code Online (Sandbox Code Playgroud)
所以这里有一个参考。但是在 ASM 中,没有对this. 确切的堆栈跟踪就像这样,它由包含“prev”attr 的实际指令组成,该指令将是加载该变量的方法:
问题是我们有所有者属性,名称属性,但我无法获得对该对象的引用。在以下情况下:
Boolean myBool2 = true;
Cemo cemo = new Cemo();
assertTrue(cemo.isTrue());
Run Code Online (Sandbox Code Playgroud)
我需要引用 ASM 中的“cemo”对象。
到目前为止我已经尝试过: - 获取框架对象,但它只包含变量“slots”,没有对它的引用。- 分析MethodInsnNode之前的指令。
我应该如何做到这一点?
JVM 是一个堆栈机器,即一个方法总是在操作数堆栈的顶部值上调用,其中this引用是非静态方法的第一个隐式参数。为了执行您的计划,您需要随时跟踪操作数堆栈上的所有参数,然后在this处理字节码中的方法调用时确定当前正在填充的值。
这意味着您需要处理方法的任何指令并跟踪任何寄存器和堆栈槽当前引用的对象。以有限的方式,这允许您跟踪调用方法的实例。但是请注意,Java(字节码)程序可能非常复杂,因为它们施加了除 Java 编程语言之外的其他限制,并允许在代码中任意跳转。基本上,为了了解某个方法在任何时间点的作用,您需要模拟一般情况下的方法调用,因此您会遇到一些相当困难的事情。