ASM look at maxStack before instructions?

为君一笑 提交于 2021-02-07 21:33:43

问题


I'm trying to use the ASM library to translate byte code into a different format, which can be done with a MethodVisitor, as with this simple test code:

    return new MethodVisitor(ASM7) {
        @Override
        public void visitInsn(int opcode) {
            System.out.println(String.format("%02x", opcode));
        }

        @Override
        public void visitMaxs(int maxStack, int maxLocals) {
            System.out.println(maxStack);
        }
    };

One issue is that I only get to see maxStack after the actual instructions – I've tested it, and that is the order the methods are called in – whereas it would be helpful to have the maxStack value available while translating the instructions.

Is there any way to get to see maxStack first?


回答1:


The ASM API does not support accessing this information before traversing the instructions.

One solution would be to traverse the class twice, storing the max values in the first pass.

The alternative is to store the current method information temporarily. ASM’s Tree API can help you here. The class MethodNode implements MethodVisitor, storing all visited artifacts and has an accept(MethodVisitor) to visit all stored artifacts:

classReader.accept(new ClassVisitor(Opcodes.ASM7) {
    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor,
                                     String signature, String[] exceptions) {
        MethodVisitor actualVisitor = new MethodVisitor(Opcodes.ASM7) {
            @Override
            public void visitInsn(int opcode) {
                System.out.printf("%02x%n", opcode);
            }

            @Override
            public void visitMaxs(int maxStack, int maxLocals) {
                System.out.println("max stack: "+maxStack);
            }
        };
        return new MethodNode(Opcodes.ASM7) {
            @Override
            public void visitMaxs(int maxStack, int maxLocals) {
                actualVisitor.visitMaxs(maxStack, maxLocals);
                super.visitMaxs(maxStack, maxLocals);
            }
            @Override
            public void visitEnd() {
                accept(actualVisitor);
            }
        };
    }
}, 0);

So here, we keep the original MethodVisitor as-is but return an adapter implementing the intended modification. It’s a subclass of MethodNode recording all artifacts but reporting visitMaxs immediately to the actualVisitor, then at visitEnd it will accept(actualVisitor) to visit all recorded information.

Note that therefore, actualVisitor will encounter visitMaxs twice, once before all other elements, then again within the standard sequence of events.




回答2:


Max stack calculated for a method depends on the instructions in and the paths thru the method's body. Hence, max stack will only be available after the method's body has been analyzed. Refer to sections 3.3.1, 3.3.2, and 3.5 here.

You could get the max stack in a separate pass and store it for reference in future passes. However, modifying the method body may likely invalidate such stored stack info.



来源:https://stackoverflow.com/questions/59865583/asm-look-at-maxstack-before-instructions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!