문제

I tried to use asm for BCI and i have a requirement where i am supposed to inject "if condition" ,so i tried using something like below

 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();
    }
}

but when i try to run i get the below exception

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)

If i comment the jump instruction things work fine.

I did some reading and came to know that there is a possibility of messing of stack map frames because of the use of JumpInstructions and also read that using of COMPUTE_FRAMES options along with SKIP_FRAMES will result in in automatic computing of stack map frames

"public static final int COMPUTE_FRAMES Flag to automatically compute the stack map frames of methods from scratch. If this flag is set, then the calls to the MethodVisitor.visitFrame(int, int, java.lang.Object[], int, java.lang.Object[]) method are ignored, and the stack map frames are recomputed from the methods bytecode. The arguments of the visitMaxs method are also ignored and recomputed from the bytecode. In other words, computeFrames implies computeMaxs."

can any one shed some light on what wrong am i doing..do i still need to compute stack map frames in case of Jump instructions?If its the case can a i get sample somewhere of how stack map frames can be computed??

Thanks

도움이 되었습니까?

해결책

The instruction introduced here:

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

...requires a boolean (integer) parameter on the stack. If the IFEQ is there, the stack is empty. If you comment out the IFEQ, the stack has the parameter. The stack underflow is caused by calling the method without the necessary parameter on the stack. This has nothing to do with stack frame maps.

다른 팁

The problem is that you're missing the argument for the first sayHello. If you want to pass the result of getCached you need to add another visitor.visitFieldInsn(GETFIELD, "com/vish/MyWrapper", "isCached", "Z"); before it.

Assuming this is what was intended, the code should be something like

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");
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top