0

我尝试将 asm 用于 BCI,并且我有一个要求我应该注入“if 条件”,所以我尝试使用类似下面的东西

 Below is the code snippet..if i comment the jump instruction things work fine..with jump instruction i see verifyerror

@Override
protected void onMethodEnter() {
    try{            
    visitor.visitVarInsn(ALOAD, 0);
    visitor.visitFieldInsn(GETFIELD, "com/vish/MyWrapper", "isCached", "Z");
    Label jump = new Label();
    visitor.visitJumpInsn(IFEQ,jump);
    visitor.visitMethodInsn(Opcodes.INVOKESTATIC, MyConstants.TO_HELPER_CLASS, "sayHello","(Z)V");
    visitor.visitVarInsn(ALOAD, 0);
    visitor.visitInsn(ICONST_1);
    visitFieldInsn(PUTFIELD, "com/vish/MyWrapper", "isCached", "Z");
    visitor.visitLabel(jump);
    visitor.visitVarInsn(ALOAD, 0);
    visitor.visitFieldInsn(GETFIELD, "com/vish/MyWrapper", "isCached", "Z");
    visitor.visitMethodInsn(Opcodes.INVOKESTATIC, MyConstants.TO_HELPER_CLASS, "sayHello",
            "()V");
    }catch(Exception e){
        e.printStackTrace();
    }
}

但是当我尝试运行时,出现以下异常

java.lang.VerifyError: JVMVRFY036 stack underflow; class=com/vish/MyWrapper, method=service()V, pc=10
       at java.lang.J9VMInternals.verifyImpl(Native Method)
       at java.lang.J9VMInternals.verify(J9VMInternals.java:72)
       at java.lang.J9VMInternals.verify(J9VMInternals.java:70)
       at java.lang.J9VMInternals.initialize(J9VMInternals.java:134)

如果我评论跳转指令一切正常。

我做了一些阅读并了解到由于使用 JumpInstructions 可能会弄乱堆栈映射帧,并且还阅读了使用 COMPUTE_FRAMES 选项以及 SKIP_FRAMES 将导致堆栈映射帧的自动计算

“public static final int COMPUTE_FRAMES 标志,用于从头开始自动计算方法的堆栈映射帧。如果设置了此标志,则调用 MethodVisitor.visitFrame(int, int, java.lang.Object[], int, java. “

任何人都可以阐明我在做什么错……在跳转指令的情况下我还需要计算堆栈映射帧吗?如果是这种情况,我可以在某处获得如何计算堆栈映射帧的样本吗?

谢谢

4

2 回答 2

1

这里介绍的指令:

visitor.visitMethodInsn(Opcodes.INVOKESTATIC, MyConstants.TO_HELPER_CLASS, "sayHello","(Z)V");

...需要堆栈上的布尔(整数)参数。如果IFEQ存在,则堆栈为空。如果您注释掉IFEQ,则堆栈具有参数。堆栈下溢是由于在堆栈上调用没有必要参数的方法引起的。这与堆栈帧映射无关。

于 2013-10-30T17:49:59.227 回答
1

问题是您缺少第一个的论点sayHello。如果你想传递结果,getCached你需要visitor.visitFieldInsn(GETFIELD, "com/vish/MyWrapper", "isCached", "Z");在它之前添加另一个。

假设这是预期的,代码应该类似于

visitor.visitVarInsn(ALOAD, 0);
visitor.visitFieldInsn(GETFIELD, "com/vish/MyWrapper", "isCached", "Z");
Label jump = new Label();
visitor.visitJumpInsn(IFEQ,jump);
visitor.visitFieldInsn(GETFIELD, "com/vish/MyWrapper", "isCached", "Z");
visitor.visitMethodInsn(Opcodes.INVOKESTATIC, MyConstants.TO_HELPER_CLASS, "sayHello","(Z)V");
visitor.visitVarInsn(ALOAD, 0);
visitor.visitInsn(ICONST_1);
visitFieldInsn(PUTFIELD, "com/vish/MyWrapper", "isCached", "Z");
visitor.visitLabel(jump);
visitor.visitVarInsn(ALOAD, 0);
visitor.visitFieldInsn(GETFIELD, "com/vish/MyWrapper", "isCached", "Z");
visitor.visitMethodInsn(Opcodes.INVOKESTATIC, MyConstants.TO_HELPER_CLASS, "sayHello",
        "()V");
于 2013-10-30T17:50:09.253 回答