java.lang.VerifyError с использованием visitJumpInsn

Я пытался использовать asm для BCI, и у меня есть требование, где я должен вводить "если условие", поэтому я попытался использовать что-то вроде ниже

 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. Метод lang.Object[]) игнорируется, а фреймы карты стека пересчитываются из байт-кода методов. Аргументы метода visitMaxs также игнорируются и пересчитываются из байт-кода. Другими словами, computeFrames подразумевает computeMaxs."

Может ли кто-нибудь пролить некоторый свет на то, что я делаю неправильно? Мне все еще нужно вычислять кадры стековой карты в случае инструкций Jump? Если это так, можно ли где-нибудь получить пример того, как можно вычислить фреймы стековой карты??

Спасибо

2 ответа

Решение

Инструкция, представленная здесь:

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

... требует логического (целочисленного) параметра в стеке. Если IFEQ там, стек пуст. Если вы закомментируете IFEQу стека есть параметр. Переполнение стека вызвано вызовом метода без необходимого параметра в стеке. Это не имеет никакого отношения к стековым картам.

Проблема в том, что вам не хватает аргумента для первого 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");
Другие вопросы по тегам