我尝试使用" insertAfter()"之后的方法使用javassist添加代码。 但运行代码时报告错误:
try {
CtClass ctClass = ClassPool.getDefault().get(className.replace('/', '.'));
CtMethod ctMethod = ctClass.getDeclaredMethod("display1");
ctMethod.insertBefore(
"name=\"我是name!这次用javassist了哦!\";" +
"value=\"我是value!\";" +
"System.out.println(\"我是加进去的哦,哈哈:\" + name);"
);
ctMethod.insertAfter("System.out.println(value);");
return ctClass.toBytecode();
} catch (Exception e) {
e.printStackTrace();
}
运行后,报告错误:
线程中的异常" main" java.lang.VerifyError:错误指令:a8
异常详细信息:
位置:
com/atlassian/api/examples/ForASMTestClass.display1()V @62: jsr
原因:
Error exists in the bytecode
字节码:
0x0000000: 2a12 28b5 0026 2a12 2cb5 002a b200 2ebb
0x0000010: 0030 59b7 0032 1234 b600 382a b400 3ab6
0x0000020: 003c b600 40b6 0042 b200 122a b400 18b6
0x0000030: 001a b200 122a b400 20b6 001a 014d a800
0x0000040: 04b1 4cb2 0044 2ab4 0046 b600 48a9 01
at transformer.modifycode.InstrumentationMain.main(InstrumentationMain.java:7)
加载类:java / lang / VerifyError
使用javap获取字节码:
public void display1();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=4, locals=4, args_size=1
0: aload_0
1: ldc #43 // String xx
3: putfield #41 // Field name:Ljava/lang/String;
6: getstatic #18 // Field java/lang/System.out:Ljava/io/PrintStream;
9: aload_0
10: getfield #24 // Field name:Ljava/lang/String;
13: invokevirtual #26 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
16: getstatic #18 // Field java/lang/System.out:Ljava/io/PrintStream;
19: aload_0
20: getfield #32 // Field value:Ljava/lang/String;
23: invokevirtual #26 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
26: goto 42
29: astore_1
30: getstatic #18 // Field java/lang/System.out:Ljava/io/PrintStream;
33: aload_0
34: getfield #32 // Field value:Ljava/lang/String;
37: invokevirtual #26 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
40: aload_1
41: athrow
42: getstatic #18 // Field java/lang/System.out:Ljava/io/PrintStream;
45: aload_0
46: getfield #32 // Field value:Ljava/lang/String;
49: invokevirtual #26 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
52: aconst_null
53: astore_3
54: jsr 58
57: return
58: astore_2
59: getstatic #45 // Field java/lang/System.out:Ljava/io/PrintStream;
62: aload_0
63: getfield #47 // Field value:Ljava/lang/String;
66: invokevirtual #49 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
69: ret 2
Exception table:
from to target type
6 29 29 any
LineNumberTable:
line 11: 6
line 12: 16
line 13: 26
line 14: 30
line 15: 40
line 14: 42
line 16: 52
LocalVariableTable:
Start Length Slot Name Signature
0 58 0 this Lcom/test/swing/ForASMTestClass;
StackMapTable: number_of_entries = 2
frame_type = 87 /* same_locals_1_stack_item */
stack = [ class java/lang/Throwable ]
frame_type = 12 /* same */
目前,我可以使用ASM在方法之后添加代码,但由于很多字节码需要手动编写,所以效率不高。
答案 0 :(得分:1)
在你的javap命令输出中,如果你还提供了类文件标题(你可以通过使用-v来实现),这将显示你的类的主要版本。
根据您提供的信息,我认为该类的主要版本是51(java 7)或52(java 8),因为在这种情况下不支持jrs操作码。< / p>
您可以阅读here(感谢@Holger提供直接web reference链接。在第一次编辑中,我使用了book reference,因为我找不到直接参考):
如果类文件版本号为51.0或更高,则jsr操作码或jsr_w操作码都不会出现在代码数组中。
这可以解释为什么你会得到验证错误。
如果我不得不猜到为什么那个操作码出现在那里我会说你使用的是一个较旧的javassist版本仍然使用JSR操作码(由finally语句使用)实现insertAfterMethod,它可能会被修复,如果你使用最新的javassist版本。
我知道这个答案更多地基于对实际&#34;确凿证据的猜测&#34;并且可能不准确。如果问题不是我所描述的,请编辑您的答案以添加更多信息,例如:
答案 1 :(得分:0)
升级Javassist(3.25.0-GA)有助于为我解决此问题。