【发布时间】:2018-03-19 18:35:26
【问题描述】:
我正在尝试生成一个简单的条件跳转指令。这是课程:
public static Class<?> getKlass2(){
String className = "TestClass";
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);
classWriter.visit(V1_8, ACC_PUBLIC, className, null, getInternalName(Object.class), null);
MethodVisitor mv = classWriter.visitMethod(ACC_PUBLIC + ACC_STATIC, "m", "()Z",null, null);
Label trueLable = new Label();
Label afterFalseLable = new Label();
mv.visitFieldInsn(GETSTATIC, getInternalName(Boolean.class), "TRUE", "Ljava/lang/Boolean;");
mv.visitMethodInsn(INVOKEVIRTUAL, getInternalName(Boolean.class), "booleanValue", "()Z", false);
mv.visitJumpInsn(IFEQ, trueLable);
mv.visitInsn(ICONST_1);
mv.visitJumpInsn(GOTO, afterFalseLable);
mv.visitLabel(trueLable);
mv.visitInsn(ICONST_0);
mv.visitFrame(F_APPEND, 0, null, 0, null);
mv.visitLabel(afterFalseLable);
mv.visitInsn(IRETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
//converting classWriter.toByteArray() to Class<?> instance
}
加载类时出现以下错误:
Expecting a stackmap frame at branch target 13
Exception Details:
Location:
TestClass.m()Z @6: ifeq
Reason:
Expected stackmap frame at this location.
Bytecode:
0x0000000: b200 0cb6 000f 9900 0704 a700 0403 ac
Stackmap Table:
same_frame_extended(@14)
但是课程的代码对我来说似乎没问题:
public class TestClass {
public static boolean m();
Code:
0: getstatic #12 // Field java/lang/Boolean.TRUE:Ljava/lang/Boolean;
3: invokevirtual #15 // Method java/lang/Boolean.booleanValue:()Z
6: ifeq 13
9: iconst_1
10: goto 14
13: iconst_0
14: ireturn
}
所以我尝试手动添加一个框架:
mv.visitFrame(F_APPEND, 0, new Object[]{ }, 0, new Object[]{ trueLabel });
但它也因同样的异常而失败。他们是否希望重新创建具有相同操作数堆栈的帧? 但这似乎毫无意义,因为我无法从 Java 代码直接访问操作数堆栈。
我做错了什么?
【问题讨论】:
-
您不想使用
new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES)为ASM 自动为您生成StackMapTable 吗? -
@apangin 没错。谢谢!!!!
-
@apangin 不要使用
COMPUTE_MAXS | COMPUTE_FRAMES; the documentation 明确声明“computeFrames 意味着 computeMaxs”,因此只需COMPUTE_FRAMES就足够了。
标签: java class if-statement jvm java-bytecode-asm