我使用 javassist 重写了一个名为 compile
的方法(该方法采用 String 数组作为参数):我创建了一个新方法,其签名为 compile
方法(它是原始方法的副本),将实际的 compile
方法重命名为 compile$Impl
并添加了对 Mine 类的一些调用。
复制是这样完成的:
CtMethod interceptMethod = CtNewMethod.copy(method, methodName, ctClass, null);
javassist重写的代码:
try {
com.company.CustomClass.instance().preintercept(this);
boolean result = compile$impl($$);
result = com.company.CustomClass.instance().dointercept(result, new Object[] { this , $1 });
return result;
} finally {
com.company.CustomClass.instance().postintercept(this);
}
代码被写入一个名为 body
的 StringBuffer 变量中,后面的变量的内容被写入新的 compile
方法的主体中,如下所示:
interceptMethod.setBody(body.toString());
ctClass.addMethod(interceptMethod);
我的com.company.CustomClass
具有由新的compile
方法调用的方法:
public Object dointercept(boolean retval, Object.. args) {
return (Boolean)returned;
}
public static synchronized CustomClass instance() {
// _instance is already instanciated when this method is called
return _instance;
}
public void preintercept(Object arg) {
// some stuff before
}
public void postintercept(Object arg) {
// some stuff after
}
执行代码时,我收到一个验证错误:
java.lang.VerifyError: (class: org/eclipse/jdt/internal/compiler/batch/Main, method: compile signature: ([Ljava/lang/String;)Z) Expecting to find integer on stack
我已将修改后的类的字节码写入磁盘,以尝试找出问题。以下是我从新的 compile
方法中获得的结果:
public boolean compile(java.lang.String[] arg0) {
try {
0 invokestatic 2130; /* com.company.CustomClass.instance() */
3 aload_0;
4 invokevirtual 2134; /* void preintercept(java.lang.Object arg0) */
7 aload_0;
8 aload_1;
9 invokevirtual 2136; /* boolean compile$impl(java.lang.String[] arg0) */
12 istore_2;
13 invokestatic 2130; /* com.company.CustomClass.instance() */
16 iload_2;
17 iconst_2;
18 anewarray 4; /* new java.lang.Object[] */
21 dup;
22 iconst_0;
23 aload_0;
24 aastore;
25 dup;
26 iconst_1;
27 aload_1;
28 aastore;
29 invokevirtual 2140; /* java.lang.Object dointercept(boolean arg0, java.lang.Object[] arg1) */
32 istore_2;
33 iload_2;
34 istore_3;
35 goto 17;
38 iload_3;
39 ireturn;
}
finally { /* covers bytes 0 to 40 */
40 astore 4;
42 invokestatic 2130; /* com.company.CustomClass.instance() */
45 aload_0;
46 invokevirtual 2143; /* void postintercept(java.lang.Object arg0) */
49 aload 4;
51 athrow;
52 invokestatic 2130; /* com.company.CustomClass.instance() */
55 aload_0;
56 invokevirtual 2143; /* void postintercept(java.lang.Object arg0) */
59 goto -21;
}
}
当我对类的字节码进行类型分析时,错误出现在第 32 行 istore_2
指令处。分析如下:
Type based analysis: compile([Ljava/lang/String;)Z
Offset Bytecode Stack before Stack after
----------------------------------------------------------------------------
0 invokestatic <empty> L
3 aload_0 L L, L
4 invokevirtual L, L <empty>
7 aload_0 <empty> L
8 aload_1 L L, L
9 invokevirtual L, L I
12 istore_2 I <empty>
13 invokestatic <empty> L
16 iload_2 L L, I
17 iconst_2 L, I L, I, I
18 anewarray L, I, I L, I, L
21 dup L, I, L L, I, L, L
22 iconst_0 L, I, L, L L, I, L, L, I
23 aload_0 L, I, L, L, I L, I, L, L, I, L
24 aastore L, I, L, L, I, L L, I, L
25 dup L, I, L L, I, L, L
26 iconst_1 L, I, L, L L, I, L, L, I
27 aload_1 L, I, L, L, I L, I, L, L, I, L
28 aastore L, I, L, L, I, L L, I, L
29 invokevirtual L, I, L L
32 istore_2 L <empty>
Error: Expecting to find I on stack, type on stack L.
33 iload_2 <empty> I
34 istore_3 I <empty>
35 goto <empty> <empty>
38 iload_3 <empty> I
39 ireturn I <empty>
40 astore L <empty>
42 invokestatic <empty> L
45 aload_0 L L, L
46 invokevirtual L, L <empty>
49 aload <empty> L
51 athrow L L
52 invokestatic <empty> L
55 aload_0 L L, L
56 invokevirtual L, L <empty>
59 goto <empty> <empty>
----------------------------------------------------------------------------
但我不明白为什么存储 int 会出现问题,因为我知道 我没有使用任何整数(我确信遗漏了一些东西)。
谢谢
最佳答案
这是因为 doIntercept
返回一个 Boolean
Object
,并且它被存储为指向对象的指针(即 L
出现在 29)。然后,它尝试将此值存储为原始 boolean 值,即原始整数 I。
如果您使用显式强制转换,或在末尾添加 .booleanValue()
com.company.CustomClass.instance().dointercept(result, new Object[] { this , $1 }).booleanValue();
这可能有用吗?
问题是它没有将对象的“自动拆箱”编译为基元。
https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html
关于java - 使用Javassist修改代码生成java.lang.VerifyError : Expecting to find integer on stack,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33676910/