0

我正在尝试使用 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

在方法中查看的来源LocalVariablesSortervisitFrame,我看到它有一个布尔值changed,如果没有更改,则visitFrame跳过对我可能创建的任何新本地人的任何考虑。此布尔值似乎仅在上游字节码对由于用于创建新changed局部变量而必须重新映射的变量执行某些操作时设置(并且在上述方法中没有发生此类操作)。LocalVariablesSorterf4()

通过应用此解决方法:

       Field field = LocalVariablesSorter.class.getDeclaredField("changed");
       field.setAccessible(true);
       field.setBoolean(this, true);

我能够通过 Java 7 的验证程序。此外,使用TraceClassVisitorASM 实用程序,我在 finally 块开始之前看到堆栈映射帧的差异:

前:

FRAME FULL [I J I] [java/lang/Throwable]

在我的反射破解之后(我添加的新本地是一个 int):

FRAME FULL [I J I I] [java/lang/Throwable]

我知道我没有共享任何周围的代码,但我的问题更笼统。这个changed布尔值是错误的优化LocalVariablesSorter吗?还是我以某种方式滥用它?

4

1 回答 1

0

LocalVariablesSorter.visitFrame(..)调用不添加任何本地变量,它仅通知 ASM 记录有关附加帧的信息。您需要通过调用添加本地人LocalVariablesSorter.newLocal(..)

虽然一般来说,如果您认为您在 ASM 中发现了错误,最好将错误报告提交给ASM 问题跟踪器并提供允许重现问题的测试代码(例如测试类和完整的转换)。

于 2013-01-24T20:46:55.200 回答