gpt4 book ai didi

java - 为什么 methodvistor.visitMaxs(0,0) 在 Java asm 中崩溃?

转载 作者:行者123 更新时间:2023-11-30 08:55:13 24 4
gpt4 key购买 nike

我正在使用 Java ASM (4.0) 编写一个简单的编译器。我使用 classWriter(COMPUTE_FRAMES) 来编写一个类。

这一切都适用于简单的程序,但是当我开始嵌套跳转时(例如 IfThenElse 语句中的 while 语句),然后我调用 methodVisitor.visitMaxs(0,0) 它会给我以下错误:

java.lang.NullPointerException
at org.objectweb.asm.Frame.a(Unknown Source)
at org.objectweb.asm.MethodWriter.visitMaxs(Unknown Source)
at front.ir.visitors.ClassWriterVisitor.visitAstProcedure(ClassWriterVisitor.java:182)
at front.ir.visitors.ClassWriterVisitor.visitAstProcedure(ClassWriterVisitor.java:1)
at front.ir.ASTProcedure.accept(ASTProcedure.java:27)
at front.ir.visitors.ClassWriterVisitor.visitProgram(ClassWriterVisitor.java:235)
at front.ir.visitors.ClassWriterVisitor.visitProgram(ClassWriterVisitor.java:1)
at front.ir.ASTProgram.accept(ASTProgram.java:37)
at front.FrontEnd.main(FrontEnd.java:122)

我的 while 语句的代码:

    jumplabels.push(new Label());

L2 = new Label();

mv.visitJumpInsn(Opcodes.GOTO, L2);
mv.visitLabel(jumplabels.peek());
whi.stmt.accept(this);
mv.visitLabel(L2);
whi.condition.accept(this);
jumplabels.pop();

还有我的 IfThenElse :

    jumplabels.push(new Label());

L2 = new Label();
L1 = new Label();

ifthenelse.condition.accept(this);
mv.visitJumpInsn(Opcodes.GOTO, L2);
mv.visitLabel(jumplabels.peek());
ifthenelse.thenStmt.accept(this);
mv.visitJumpInsn(Opcodes.GOTO, L1);
mv.visitLabel(L2);
if (ifthenelse.elseStmt != null) {
ifthenelse.elseStmt.accept(this);
}
mv.visitLabel(L1);

jumplabels.pop();

condition.accept(this) 将插入正确的条件并跳转到压入堆栈的最后一个标签(例如 IFEQ jumplabels.peek())。

我希望任何人都可以告诉我我做错了什么。对于可能不清楚的代码,我们深表歉意。

最佳答案

我不知道你究竟做错了什么,但此时的崩溃总是表明你写的字节码在某种程度上是不正确的。当我们点击它时,我们在启用调试开关的情况下再次运行它,其中调试开关触发对 CheckClassAdapter.verify() 的调用,它会生成一个字节码列表,通过练习,您可以通过解释来确定您去了哪里错了。

为了回答您的问题,以下是我们所做工作的更多详细信息。

我们实际上有两个选项可以设置,称为displayByteCodedebugByteCode。 display 选项无条件地将字节码打印到文件中,debug 选项只有在出现问题时才会起作用。

首先,我们创建一个 ClassWriter cw,我们用它来创建类。如果 displayByteCode 选项打开,那么我们立即将其包装在 TraceClassVisitor 中,给它一个 PrintWriter,生成的字节码将写入其中。

完成时(在调用 cw.visitEnd() 之后),如果 debugByteCode 选项打开,我们将执行以下操作:

StringWriter sw = new StringWriter();
CheckClassAdapter.verify(new ClassReader(cw.toByteArray()), false, new PrintWriter(sw));
if (sw.toString().length() != 0) {
System.err.println("Verify Output for " + objectName + ":");
try {
BufferedWriter out = new BufferedWriter(new FileWriter("ByteCodeOutput.txt"));
out.write(sw.toString());
out.close();
} catch (IOException e) {
System.out.println("Exception " + e);
}
System.err.println(sw);
throw new IllegalStateException("Bytecode failed verification");
}

这段代码几乎肯定可以改进,但由于它只在紧急情况下需要,所以它足以满足我们的目的。

关于java - 为什么 methodvistor.visitMaxs(0,0) 在 Java asm 中崩溃?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29150607/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com