Java BCEL能否生成LocalVariableTable?
我遇到了一个无聊的错误:Java BCEL能否生成LocalVariableTable?,java,bytecode,javassist,bcel,Java,Bytecode,Javassist,Bcel,我遇到了一个无聊的错误: Exception in thread "main" java.lang.VerifyError: Bad type on operand stack in method net.madz.lifecycle.demo.standalone.ServiceOrder.allocateResources(JJJ)V at offset 27 我不太明白这个错误的意思 我编写了一个类并生成了一个类,它们看起来非常相似: 写道: public v
Exception in thread "main" java.lang.VerifyError: Bad type on operand stack in method
net.madz.lifecycle.demo.standalone.ServiceOrder.allocateResources(JJJ)V at offset 27
我不太明白这个错误的意思
我编写了一个类并生成了一个类,它们看起来非常相似:
写道:
public void allocateResources(long arg0, long truckResourceId, long arg2) {
/* L23 */
0 new 2;
3 dup;
4 invokespecial 3; /* net.madz.lifecycle.solutionOne.InterceptorController() */
7 astore 7; /* controller */
/* L24 */
9 new 4;
12 dup;
13 aload_0; /* this */
14 invokevirtual 5; /* java.lang.Class getClass() */
17 aload_0; /* this */
18 ldc 6; /* "allocateResources" */
20 iconst_3;
21 anewarray 7; /* new java.lang.Class[] */
24 dup;
25 iconst_0;
26 getstatic 8; /* java.lang.Long.TYPE */
29 aastore;
30 dup;
31 iconst_1;
32 getstatic 8; /* java.lang.Long.TYPE */
35 aastore;
36 dup;
37 iconst_2;
38 getstatic 8; /* java.lang.Long.TYPE */
41 aastore;
42 invokespecial 9; /* net.madz.lifecycle.solutionOne.InterceptContext(java.lang.Class summaryPlanId, java.lang.Object arg1, java.lang.String truckResourceId, java.lang.Class[] arg3) */
45 astore 8; /* context */
/* L26 */
47 aload 7; /* controller */
49 aload 8; /* context */
51 new 10;
54 dup;
55 aload_0; /* this */
56 lload_1; /* summaryPlanId */
57 lload_3; /* truckResourceId */
58 lload 5; /* plangResourceId */
60 invokespecial 11; /* net.madz.lifecycle.solutionOne.ServiceOrder$1(net.madz.lifecycle.solutionOne.ServiceOrder summaryPlanId, long arg1, long truckResourceId, long arg3) */
63 invokevirtual 12; /* java.lang.Object exec(net.madz.lifecycle.solutionOne.InterceptContext arg0, java.util.concurrent.Callable truckResourceId) */
66 pop;
/* L34 */
67 return;
}
生成:
public void allocateResources(long arg0, long arg1, long arg2) {
0 new 77;
3 dup;
4 invokespecial 78; /* net.madz.lifecycle.solutionOne.InterceptorController() */
7 astore 7;
9 new 80;
12 dup;
13 ldc 7;
15 aload_0;
16 ldc 81; /* "allocateResources" */
18 iconst_3;
19 anewarray 83; /* new java.lang.Class[] */
22 dup;
23 iconst_0;
24 getstatic 88; /* java.lang.Long.TYPE */
27 aastore;
28 dup;
29 iconst_1;
30 getstatic 88; /* java.lang.Long.TYPE */
33 aastore;
34 dup;
35 iconst_2;
36 getstatic 88; /* java.lang.Long.TYPE */
39 aastore;
40 invokespecial 91; /* net.madz.lifecycle.solutionOne.InterceptContext(java.lang.Class arg0, java.lang.Object arg1, java.lang.String arg2, java.lang.Class[] arg3) */
43 astore 8;
45 aload 7;
47 aload 8;
49 new 93;
52 dup;
53 aload_0;
54 lload_1;
55 lload_3;
56 lload 5;
58 invokespecial 96; /* net.madz.lifecycle.demo.standalone.ServiceOrder$5(net.madz.lifecycle.demo.standalone.ServiceOrder arg0, long arg1, long arg2, long arg3) */
61 invokevirtual 100; /* java.lang.Object exec(net.madz.lifecycle.solutionOne.InterceptContext arg0, java.util.concurrent.Callable arg1) */
64 pop;
65 return;
}
因为它说“net.madz.lifecycle.demo.standalone.ServiceOrder.allocateResources(JJJ)V方法中的操作数堆栈在偏移量27处的类型不正确”
是“27 aastore;”导致了这一异常吗?在编写的版本类中,我的意思是我编写了一个java文件并将其编译成类文件。我使用这个.getClass()来加载类引用,因此在编写的版本中,“offset”13和14是“aload_0;”和“invokevirtual 5;”,但在生成的版本中,我使用偏移量13处的“ldc”直接引用类,因此这两个版本无法精确对齐
通常,如何诊断这些问题以及如何在运行时监控操作数堆栈,BCEL能否将LocalVariableTable生成类文件?最后,我尝试利用BCEL从生成的类文件和写入的类文件生成Java代码,我发现了它们之间的差异
public static void main(String[] args) throws Throwable {
final JavaClass outerClass = Repository.lookupClass(ServiceOrder.class.getName());
StringRepresentation s = new StringRepresentation(outerClass);
System.out.println(s);
BCELifier fier = new BCELifier(outerClass, System.out);
fier.start();
final JavaClass outer2Class = Repository.lookupClass(net.madz.lifecycle.solutionOne.ServiceOrder.class.getName());
BCELifier fier2 = new BCELifier(outer2Class, System.out);
fier2.start();
然后找到了不同的部分:
正确:
il.append(_factory.createFieldAccess("java.lang.Long", "TYPE", new ObjectType("java.lang.Class"), Constants.GETSTATIC));
错:
il.append(_factory.createFieldAccess("java.lang.Long", "TYPE", Type.LONG, Constants.GETSTATIC));
在我的代码中,实际上我正在使用:
ilist.append(ifact.createGetStatic(convertType2ClassName(type), "TYPE", Type.LONG));
显然应该是:
ilist.append(ifact.createGetStatic(convertType2ClassName(type), "TYPE", new ObjectType("java.lang.Class")));
总之,我犯了两个错误: