我使用classloader和Unsafe :: definedAnonymous()来加载生成的字节码byte []。 classLoader.loadClass()返回的Class的使用成功,而c.getMethod()
API中的c=Unsafe.defineAnonymousClass()
失败。那么生成的字节码是错的吗?
我的代码:
MainInliner loader = new MainInliner();
Class<?> c =null;
byte[] bytes = ...
if(args[0].equals("0")){
c = loader.loadClass(name, bytes, 0, bytes.length); // Classloader.loadClass.
}else{
c = Unsafe.defineAnonymousClass(Hoster, bytes, null);
}
Method m = c.getMethod("main", new Class<?>[] { String[].class });
错误是:
Exception Details:
Location:
code/sxu/asm/example/Caller.test(II)V @98: lload_3
Reason:
Type integer (current frame, locals[3]) is not assignable to long
Current Frame:
bci: @98
flags: { }
locals: { 'code/sxu/asm/example/Caller', integer, integer, integer, integer, integer, integer, integer, integer, integer }
stack: { 'java/io/PrintStream' }
Bytecode:
0000000: 1b85 2ab4 000e 1b1c 3e36 043a 0537 0619
0000010: 05b4 002a b600 3019 05b4 0033 b600 3060
0000020: 3608 1508 3609 1606 1509 a700 0385 6542
0000030: 1b2a b400 0e1c 033e 3604 3a05 3606 1905
0000040: b400 2ab6 0030 1905 b400 33b6 0030 6036
0000050: 0715 0736 0815 0615 08a7 0003 6036 05b2
0000060: 003d 21b6 0043 b1
Stackmap Table:
full_frame(@45,{Object[#2],Integer,Integer,Integer,Integer,Object[#21],Long,Integer,Integer},{Long,Integer})
full_frame(@92,{Object[#2],Integer,Integer,Integer,Integer,Object[#21],Integer,Integer,Integer,Integer},{Integer,Integer})
,生成的字节码为:
public void test(int, int);
flags: ACC_PUBLIC
Code:
stack=5, locals=10, args_size=3
0: iload_1
1: i2l
2: aload_0
3: getfield #14 // Field _callee:Lcode/sxu/asm/example/Callee;
6: iload_1
7: iload_2
8: istore_3
9: istore 4
11: astore 5
13: lstore 6
15: aload 5
17: getfield #42 // Field code/sxu/asm/example/Callee._a:Ljava/lang/String;
20: invokevirtual #48 // Method java/lang/String.length:()I
23: aload 5
25: getfield #51 // Field code/sxu/asm/example/Callee._b:Ljava/lang/String;
28: invokevirtual #48 // Method java/lang/String.length:()I
31: iadd
32: istore 8
34: iload 8
36: istore 9
38: lload 6
40: iload 9
42: goto 45
45: i2l
46: lsub
47: lstore_3 //r..
48: iload_1
49: aload_0
50: getfield #14 // Field _callee:Lcode/sxu/asm/example/Callee;
53: iload_2
54: iconst_0
55: istore_3
56: istore 4
58: astore 5
60: istore 6 //The backup stack bottom variable.
62: aload 5
64: getfield #42 // Field code/sxu/asm/example/Callee._a:Ljava/lang/String;
67: invokevirtual #48 // Method java/lang/String.length:()I
70: aload 5
72: getfield #51 // Field code/sxu/asm/example/Callee._b:Ljava/lang/String;
75: invokevirtual #48 // Method java/lang/String.length:()I
78: iadd
79: istore 7
81: iload 7
83: istore 8
85: iload 6 //Push back 6
87: iload 8 //Repush 8
89: goto 92
//return calculate()
92: iadd
93: istore 5
95: getstatic #61 // Field java/lang/System.out:Ljava/io/PrintStream;
98: lload_3
99: invokevirtual #67 // Method java/io/PrintStream.println:(J)V
102: return
LocalVariableTable:
Start Length Slot Name Signature
15 30 5 this Lcode/sxu/asm/example/Callee;
15 30 4 t I
15 30 3 p I
34 11 8 tmp I
62 30 5 this Lcode/sxu/asm/example/Callee;
62 30 4 t I
62 30 3 p I
81 11 7 tmp I
0 103 0 this Lcode/sxu/asm/example/Caller;
0 103 1 a I
0 103 2 b I
48 55 3 r J
95 8 5 c I
LineNumberTable:
line 19: 0
line 16: 15
line 23: 34
line 21: 48
line 16: 62
line 23: 81
line 23: 95
line 30: 102
StackMapTable: number_of_entries = 2
frame_type = 255 /* full_frame */
offset_delta = 45
locals = [ class code/sxu/asm/example/Caller, int, int, int, int, class code/sxu/asm/example/Callee, long, int, int ]
stack = [ long, int ]
frame_type = 255 /* full_frame */
offset_delta = 46
locals = [ class code/sxu/asm/example/Caller, int, int, int, int, class code/sxu/asm/example/Callee, int, int, int, int ]
stack = [ int, int ]
}
此字节码对应于内联Callee方法。
我检查了这个字节码序列,似乎没有错误。错误消息中的变量3出现4次,其中:
8: istore_3 //Popo up existing parameters for inlining.
47: lstore_3 //r. The local variable in the Caller method
55: istore_3 // Similiar to the label 8, pops stack paras to local variable.
98: lload_3 //Println parameter
相应的方法是:
public class Caller{
public void test(int a, int b){
long r = (long)a- _callee.calculate(a, b);
int c = a +_callee.calculate(b, 0);
System.out.println(r);
}
}
public class Callee{
public int calculate(int t, int p){
int tmp=_a.length()+_b.length();
return tmp;
}}