javassist无法编译:异常:堆栈高度不一致-1

问题描述 投票:0回答:1

我正在尝试使用javassist在加载时修改某些测试类的字节码。

这就是我想要做的:

for (CtMethod ctm : ctc.getDeclaredMethods()) {

    ctm.instrument(
            new ExprEditor() {
                public void edit(MethodCall m) throws CannotCompileException{
                    m.replace("{"
                            + "try {"
                                + "$_ = $proceed($$);" 
                                + "} catch(Exception e) {" 
                                + "    System.err.println(e); " 
                                + "  }" 
                            + "}"
                                    );
                        }

                    });
        }
    }
}

ctc:CtClass类的一个对象:正在加载的类(它来自我的翻译器implmentation中的onLoad方法)

ctm:类ctc上的一个方法。

基本上,我正在尝试做一些简单的事情:对于在类加载时声明的每个方法,我想要检测该方法,替换该方法中的每个方法调用,包含在try-catch中。是的我知道我有函数addCatch,但这不符合我的最终目的,我需要在这里使用表达式编辑器。

这是我正在运行的类来测试这个:

public class B {

    public double bar(int x) {
        System.out.println("Inside B.bar");
        return (1 / x);
    }

}

我想把这个课变成:

public class B {

    public double bar(int x) {
        try {
        System.out.println("Inside B.bar");
        } catch (Exception e) {
          System.err.println(e);
        }
        return (1 / x);
    }
}

(是的,我知道这很奇怪,但我想让它工作。但是,每次我尝试它时,我都会遇到以下错误:

javassist.CannotCompileException: ... : inconsistent stack height -1
...
Caused by: javassist.bytecode.BadBytecode: ... inconsistent stack height -1

Expecting a stackmap frame at branch target 30
Exception Details:
  Location:
    test/Example.main([Ljava/lang/String;)V @21: aload_1
  Reason:
    Expected stackmap frame at this location.
  Bytecode:
    0000000: b200 10bb 0016 59b7 0018 bb00 1959 b700
    0000010: 1b4d 4c0e 4a2b 2cb6 001c 4aa7 0010 3a05
    0000020: b200 2e19 05b6 0031 a700 0329 494c 2b28
    0000030: b600 2001 3a04 a700 103a 05b2 002e 1905
    0000040: b600 31a7 0003 b1      

任何人都知道这个错误吗?堆栈高度不一致?我看了谷歌,没有出现。

javassist
1个回答
1
投票

在ExprEditor.MethodCall.replace(String)调用中使用Try / Catch块导致堆栈错误不一致:

https://issues.jboss.org/browse/JASSIST-210

The tutorial在第4.2节中也提到了这一点(“它不能包含或包含try-catch语句。”)

这是因为Try / Catch机制中涉及的复杂性,特别是:

“如果在try块中抛出异常,则会弹出堆栈中的所有值。”

replace()函数不考虑这一点,因此不会生成适当的字节码。 addCatch()方法可以。

© www.soinside.com 2019 - 2024. All rights reserved.