我正在尝试使用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类的一个对象:正在加载的类(它来自我的翻译器实现的onLoad方法)
ctm :类ctc上的方法。
基本上,我正在尝试做一些简单的事情:对于在类加载时声明的每个方法,我想要检测该方法,替换该方法中的每个方法调用,包含在尝试中-抓住。
是的我知道我有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
任何人都知道这个错误吗?堆栈高度不一致?我看了谷歌,什么都没有出现。
答案 0 :(得分: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()方法可以。