I tried to use javassist add code after method with "insertAfter()". But error reported when running the code:
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();
}
After running it, error reported:
Exception in thread "main" java.lang.VerifyError: Bad instruction: a8
Exception Details:
Location:
com/atlassian/api/examples/ForASMTestClass.display1()V @62: jsr
Reason:
Error exists in the bytecode
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)
load class:java/lang/VerifyError
Used javap to get the bytecode:
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 */
Currently, i can use ASM to add code after method, but it is not efficient since a lot of bytecode need to write mannually.