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");