问题
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