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

javassist cannot compile: exception: inconsistent stack height -1

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

这就是我想要做的:

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:class CtClass 的一个对象:正在加载的 class(它来自我的翻译器实现中的 onLoad 方法)

ctm: class ctc.

上的一个方法

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

这是 class 我正在 运行 测试这个:

public class B {

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

}

我想把这个class改造成:

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      

有人知道这个错误吗?堆叠高度不一致?我查看了 google,但什么也没有。

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

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

The tutorial 在第 4.2 节中也提到了这一点 ("It cannot be or contain a try-catch statement.")

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

"If an exception is thrown in the try block, then all the values in the stack are popped out."

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