为什么ASM无法找出我的生成类的正确最大值?

时间:2013-01-06 09:20:28

标签: java bytecode java-bytecode-asm

我正在使用ASM 3.1生成一个虚拟类。它只有一个简单的构造函数,没有其他方法:

public class TestAsm {

public static void main(String... args) throws Throwable {
    ClassWriter sw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
    sw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER, "test/SubCls", null, "test/SuperCls", null);
    sw.visitField(Opcodes.ACC_PUBLIC, "i", "I", null, null);

    MethodVisitor mv = sw.visitMethod(0, "<init>", "()V", null, null);
    // mv.visitMaxs(2, 1);
    mv.visitCode();
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "test/SuperCls", "<init>", "()V");
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitInsn(Opcodes.ICONST_2);
    mv.visitFieldInsn(Opcodes.PUTFIELD, "test/SubCls", "i", "I");
    mv.visitInsn(Opcodes.RETURN);
    mv.visitEnd();

    sw.visitEnd();
    byte[] cls = sw.toByteArray();
    FileOutputStream fos = new FileOutputStream("bin/test/SubCls.class");
    fos.write(cls);
    fos.close();

    SuperCls o = (SuperCls) Class.forName("test.SubCls").newInstance();
    System.out.println(o.i);

    System.out.println(o.getClass().getDeclaredField("i").getInt(o));
    }
}

正如您所看到的,我根据文档指定了ClassWriter.COMPUTE_FRAMES标志,它将计算我所有方法的堆栈大小和本地大小。但是当我运行此代码时,我收到一个错误:

Exception in thread "main" java.lang.VerifyError: (class: test/SubCls, method: <init> signature: ()V) Stack size too large
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:169)
at test.TestAsm.main(TestAsm.java:33)

我使用'javap -c'检查了生成的类文件,发现堆栈大小和本地大小不正确:

$ javap -c SubCls -verbose
public class test.SubCls extends test.SuperCls
minor version: 0
major version: 50
Constant pool:
const #1 = Asciz    test/SubCls;
const #2 = class    #1; //  test/SubCls
const #3 = Asciz    test/SuperCls;
const #4 = class    #3; //  test/SuperCls
const #5 = Asciz    i;
const #6 = Asciz    I;
const #7 = Asciz    <init>;
const #8 = Asciz    ()V;
const #9 = NameAndType  #7:#8;//  "<init>":()V
const #10 = Method  #4.#9;  //  test/SuperCls."<init>":()V
const #11 = NameAndType #5:#6;//  i:I
const #12 = Field   #2.#11; //  test/SubCls.i:I
const #13 = Asciz   Code;

{
public int i;


test.SubCls();
  Code:
   Stack=0, Locals=1, Args_size=1
   0:   aload_0
   1:   invokespecial   #10; //Method test/SuperCls."<init>":()V
   4:   aload_0
   5:   iconst_2
   6:   putfield    #12; //Field i:I
   9:   return

}

当我手动调用visitMaxs(2, 1)时,此错误将消失 但我不知道为什么ASM无法为我计算正确的最大值。谁能给我一个暗示?

1 个答案:

答案 0 :(得分:3)

致电mv.visitMaxs(0, 0);;我确实在某个地方读过这篇文章,发现我记得很奇怪。