ASM looks at the instructions before maxStack?
I’m trying to convert bytecode to a different format using the ASM library, which can be done using MethodVisitor, just like 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 problem is that I can only see maxStack after the actual instructions – I’ve tested it, this is the order in which the methods are called – and it would be helpful to provide the maxStack value when translating the instructions
Is there any way to see maxStack first?
Solution
The ASM API does not support accessing this information before traversing the instructions.
One solution is to traverse the class twice, storing the maximum value on the first traversal.
Another method is to temporarily store the current method information. ASM’s Tree API can help you in this regard. The MethodNode
class implements MethodVisitor, stores all visited artifacts, and has an accept(MethodVisitor)
to access 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 leave the original MethodVisitor
unchanged, but return an adapter that implements the expected modifications. It is a subclass of MethodNode
that logs all artifacts, but immediately reports visitMaxs
to actualVisitor, and then at visitEnd
it will accept (actualVisitor)
access all recorded information.
So note that actualVisitor
will encounter visitMaxs
twice, once before all other elements, and then again in the standard sequence of events.