简体   繁体   English

CheckClassAdapter 是否需要为 visitMaxs 使用精确值?

[英]Does CheckClassAdapter require using precise values for visitMaxs?

When creating a class using ASM, it is convenient to pass meaningless values to visitMaxs使用ASM创建class时,方便传递无意义的值给visitMaxs

public static byte[] createClassNoAdapter() {
    var cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);

    cw.visit(Opcodes.V9, ACC_PUBLIC, "TestClass", null, "java/lang/Object" , new String[0]);

    var mv = cw.visitMethod(ACC_PUBLIC, "test", "()V", null, null);
    mv.visitCode();
    mv.visitInsn(Opcodes.RETURN);
    mv.visitMaxs(-1, -1);
    mv.visitEnd();

    return cw.toByteArray();
}

However, I'm trying to diagnose some problems, and using a CheckClassAdapter .但是,我正在尝试诊断一些问题,并使用CheckClassAdapter If I explicitly pass correct values for maxStack and maxLocals , this works.如果我明确传递maxStackmaxLocals的正确值,则此方法有效。

public static byte[] createClassAdapter() {
    var cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);

    var cv = new CheckClassAdapter(cw);
    cv.visit(Opcodes.V9, ACC_PUBLIC, "TestClass2", null, "java/lang/Object" , new String[0]);

    var mv = cv.visitMethod(ACC_PUBLIC, "test", "()V", null, null);
    mv.visitCode();
    mv.visitInsn(Opcodes.RETURN);
    mv.visitMaxs(1, 1);
    mv.visitEnd();

    return cw.toByteArray();
}

While this works, it's less convenient.虽然这可行,但不太方便。 Calling visitMaxs(-1, -1) results in an error:调用visitMaxs(-1, -1)会导致错误:

java.lang.IllegalArgumentException: Invalid max stack (must be an unsigned short): -1
    at org.objectweb.asm.util.CheckMethodAdapter.checkUnsignedShort(CheckMethodAdapter.java:1133)
at org.objectweb.asm.util.CheckMethodAdapter.visitMaxs(CheckMethodAdapter.java:1027)
at com.justinblank.strings.Example.createClassAdapter(Example.java:35)
at com.justinblank.strings.Example.main(Example.java:47)

The source code makes it clear that you must pass a non-negative value, but passing 0 does not work either:源代码清楚地表明您必须传递一个非负值,但传递 0 也不起作用:

java.lang.IllegalArgumentException: Data flow checking option requires valid, non zero maxLocals and maxStack.
    at org.objectweb.asm.util.CheckMethodAdapter$1.visitEnd(CheckMethodAdapter.java:456)
    at org.objectweb.asm.MethodVisitor.visitEnd(MethodVisitor.java:783)
    at org.objectweb.asm.util.CheckMethodAdapter.visitEnd(CheckMethodAdapter.java:1036)
    at com.justinblank.strings.Example.createClassAdapterZero(Example.java:51)
    at com.justinblank.strings.Example.main(Example.java:65)
Caused by: java.lang.IndexOutOfBoundsException: Trying to set an inexistant local variable 0
    at org.objectweb.asm.tree.analysis.Frame.setLocal(Frame.java:208)
    at org.objectweb.asm.tree.analysis.Analyzer.computeInitialFrame(Analyzer.java:466)
    at org.objectweb.asm.tree.analysis.Analyzer.analyze(Analyzer.java:163)
    at org.objectweb.asm.util.CheckMethodAdapter$1.visitEnd(CheckMethodAdapter.java:453)
    ... 4 more

Is there some way to avoid manually calculating the stack while using CheckClassAdapter?有什么方法可以避免在使用 CheckClassAdapter 时手动计算堆栈?

It appears that it's safe to use a very large value.使用非常大的值似乎是安全的。 The following value seemed to work for me in several cases:在几种情况下,以下值似乎对我有用:

public static byte[] createClassAdapterHacky() {
    var cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);

    var cv = new CheckClassAdapter(cw);
    cv.visit(Opcodes.V9, ACC_PUBLIC, "TestClass3", null, "java/lang/Object" , new String[0]);

    var mv = cv.visitMethod(ACC_PUBLIC, "test", "()V", null, null);
    mv.visitCode();
    mv.visitMaxs(Short.MAX_VALUE * 2 + 1, Short.MAX_VALUE * 2 + 1);
    mv.visitEnd();

    return cw.toByteArray();
}

I don't know for sure if this is the proper solution, but it seems to work.我不确定这是否是正确的解决方案,但它似乎有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM