ASM COMPUTE_MAXS不适用于基本测试用例?

时间:2012-05-18 05:43:16

标签: java java-bytecode-asm

帖子的底部是测试用例。它给出以下错误。但是我设置了new ClassWriter(ClassWriter.COMPUTE_MAXS)所以不应该自动计算最大堆栈并正确设置它吗?

Exception in thread "main" java.lang.RuntimeException: Error at instruction 2: Insufficient maximum stack size. testMethod()Ljava/lang/Object;
00000  :  :    L0
00001  :  :     LINENUMBER 22 L0
00002  :  :     ACONST_NULL
00003 ? :     ARETURN

测试用例:

public static void main(String[] args) {
    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    CheckClassAdapter cv = new CheckClassAdapter(cw);
    cv.visit(V1_7, ACC_PUBLIC + ACC_SUPER, "path/Cls", null, "java/lang/Object", null);
    {
        MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
        mv.visitInsn(RETURN);
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitLocalVariable("this", "L" + "path/Cls" + ";", null, l0, l1, 0);
        mv.visitMaxs(1, 1);
        mv.visitEnd();
    }
    {
        MethodVisitor mv = cv
                .visitMethod(ACC_PUBLIC + ACC_STATIC, "testMethod", "()Ljava/lang/Object;", null, null);
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitLineNumber(22, l0);
        mv.visitInsn(ACONST_NULL);
        mv.visitInsn(ARETURN);
        mv.visitMaxs(0, 0); // Same error even if this is commented out
        mv.visitEnd();
    }

    byte[] byteArray = cw.toByteArray();
}

2 个答案:

答案 0 :(得分:4)

问题不在于ASM,而在于您的测试。基本上,CheckClassAdapter在最大堆栈之前看到字节码,并计算var值。

您可以将代码更改为以下内容:

  ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
  cw.visit...

  byte[] byteArray = cw.toByteArray();
  ClassReader cr = new ClassReader(byteArray);
  cr.accept(new CheckClassAdapter(new ClassWriter(0)), 0);

答案 1 :(得分:0)

您可以将CheckClassAdapter配置为不检查堆栈大小:

CheckClassAdapter cv = new CheckClassAdapter(cw, false);