我正在尝试使用 ASM 将方法包装在 try/finally 块中。具体来说,我正在扩展org.objectweb.asm.commons.AdviceAdapter
并遵循“3.2.3 在方法退出前插入代码”下描述的“使用 ASM 框架实现常见字节码转换模式”的技术。
我还使用LocalVariablesSorter
(的超类AdviceAdapter
)在我在 finally 块中使用的方法 start 处添加一个局部变量。
我有一个尝试用 ASM 修改的方法。该方法需要三个参数,并且没有自己的局部变量:
class Example {
public static int f4(int i, long l, int f) {
return (int) (i + l + f);
}
}
由于我的finally
块可能是异常处理程序目标,因此我添加了一个调用 so super.visitFrame(F_NEW, ...)
,传递方法参数。由于这调用了超类,我希望我的 newLocal 被添加到这个框架中LocalVariablesSorter
。但是当通过我的 ASM 管道运行它时,Java 7 给了我错误java.lang.VerifyError: Bad local variable type in method Example.f4(IJI)I at offset 32
。
在方法中查看的来源LocalVariablesSorter
visitFrame
,我看到它有一个布尔值changed
,如果没有更改,则visitFrame
跳过对我可能创建的任何新本地人的任何考虑。此布尔值似乎仅在上游字节码对由于用于创建新changed
局部变量而必须重新映射的变量执行某些操作时设置(并且在上述方法中没有发生此类操作)。LocalVariablesSorter
f4()
通过应用此解决方法:
Field field = LocalVariablesSorter.class.getDeclaredField("changed");
field.setAccessible(true);
field.setBoolean(this, true);
我能够通过 Java 7 的验证程序。此外,使用TraceClassVisitor
ASM 实用程序,我在 finally 块开始之前看到堆栈映射帧的差异:
前:
FRAME FULL [I J I] [java/lang/Throwable]
在我的反射破解之后(我添加的新本地是一个 int):
FRAME FULL [I J I I] [java/lang/Throwable]
我知道我没有共享任何周围的代码,但我的问题更笼统。这个changed
布尔值是错误的优化LocalVariablesSorter
吗?还是我以某种方式滥用它?