java - 操作数栈欠载

标签 java bytecode

我有这个程序可以从 java 文件生成字节码。 对于这个简单的 test() 方法

public void test()
{
    boolean a = false;
    if (a || true)
    {
         boolean b = false;
    }
}

,它将生成以下字节码

public void test()
  Code:
   7:   iconst_0
   8:   istore_1
   9:   iload_1
   10:  ifne    13
   13:  iconst_0
   14:  istore_2
   15:  return

当我执行该类时,我不断遇到Operand stack underrun in test(),我无法弄清楚为什么,因为生成的字节码(对我来说)看起来不错

谁能帮我调试这个吗?

(这是我跟踪堆栈的方法

public void test()
  Code:
   7:   iconst_0
 (1 on the stack)
   8:   istore_1
 (0 on the stack)
   9:   iload_1
 (1 on the stack)
   10:  ifne    13
 (0 on the stack)
   13:  iconst_0
 (1 on the stack)
   14:  istore_2
 (0 on the stack)
   15:  return

是的,堆栈对我来说看起来不错!)

编辑:这是由 javac 生成的字节码

public void test();
  Code:
   0:   iconst_0
   1:   istore_1
   2:   iload_1
   3:   ifne    6
   6:   iconst_0
   7:   istore_2
   8:   return

最佳答案

当我尝试这个时

public class MainDump implements Opcodes {

    public static byte[] dump() throws Exception {

        ClassWriter cw = new ClassWriter(0);
        FieldVisitor fv;
        MethodVisitor mv;
        AnnotationVisitor av0;

        cw.visit(V1_7, ACC_PUBLIC + ACC_SUPER, "Main", null, "java/lang/Object", null);

        cw.visitSource("Main.java", null);

        {
            mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
            mv.visitCode();
            Label l0 = new Label();
            mv.visitLabel(l0);
            mv.visitLineNumber(1, l0);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
            mv.visitInsn(RETURN);
            Label l1 = new Label();
            mv.visitLabel(l1);
            mv.visitLocalVariable("this", "LMain;", null, l0, l1, 0);
            mv.visitMaxs(1, 1);
            mv.visitEnd();
        }
        {
            mv = cw.visitMethod(ACC_PUBLIC, "test", "()V", null, null);
            mv.visitCode();
            mv.visitInsn(ICONST_0);
            mv.visitVarInsn(ISTORE, 1);
            mv.visitVarInsn(ILOAD, 1);
            Label l2 = new Label();
            mv.visitJumpInsn(IFEQ, l2);
            mv.visitInsn(ICONST_0);
            mv.visitVarInsn(ISTORE, 2);
            mv.visitLabel(l2);
            mv.visitFrame(Opcodes.F_APPEND, 1, new Object[]{Opcodes.INTEGER}, 0, null);
            mv.visitInsn(RETURN);
            mv.visitMaxs(1, 3);
            mv.visitEnd();
        }
        cw.visitEnd();

        return cw.toByteArray();
    }

    public static void main(String... ignored) throws Exception {
        Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
        defineClass.setAccessible(true);

        byte[] dump = dump();
        defineClass.invoke(Thread.currentThread().getContextClassLoader(), dump, 0, dump.length);
        new Main().test();
    }
}

这有效,但是如果我放弃堆栈帧调整,则会收到此错误

Exception in thread "main" java.lang.VerifyError: Expecting a stackmap frame at branch target 8
Exception Details:
  Location:
    Main.test()V @3: ifeq
  Reason:
    Expected stackmap frame at this location.
  Bytecode:
    0000000: 033c 1b99 0005 033d b1  

简而言之,对于Java 7来说,堆栈操作不足以通过有效性。

关于java - 操作数栈欠载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18985248/

相关文章:

java - Selenium : I am Using Firefox version 46. 01 并在 eclipse 中测试显示错误消息

java - 背景音乐线程在游戏中死亡而不是暂停

java - 如何重用asm中methodNode的原始帧信息来创建 `org.objectweb.asm.tree.analysis.Frame`

java - 如何读取ASM中的最终字符串值?

python - 从 Python AST 生成 .pyc?

java - 向 smali 源添加代码

java - 是否可以根据函数动态生成 JavaFX TreeItem 的子项?

java - Android Studio - 文件是只读的

java - 如何在eclipse中运行maven项目(打印出 "Hello Word")

java - "There are better ways to describe semantics than Java bytecodes"?