繁体   English   中英

使用 Javassist 修改代码生成 java.lang.VerifyError: Expecting to find integer on stack

[英]Code modification with Javassist generate a java.lang.VerifyError: Expecting to find integer on stack

我使用 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

}

执行代码时,我得到了一个 verifyError:

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 ,并将其存储为指向对象的指针(即出现在 29 处的L )。 然后它尝试将此值存储到原始boolean ,即原始整数I

如果您使用显式转换,或在末尾添加.booleanValue()

com.company.CustomClass.instance().dointercept(result, new Object[] { this , $1 }).booleanValue();

它可能工作吗?

问题是它没有将对象的“自动拆箱”编译为基元。

https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM