Reputation: 2630
I need to write code which inserts instructions into a method at a specified position. The way that I specify the position is by providing the number of the instruction immediately before it. The idea is to visit all instructions until the number of the instruction equals the specified number (so the first instruction is the 0th instruction, the next instruction is the first instruction, etc.), which, at that point, the instructions that I want to inject will be injected. The problem is that there is no generic "visit instruction" method in the MethodVisitor
class; it only has methods for visiting specific type of instructions, so I cannot figure out an elegant way of visiting the nth instruction. Here is what I came up with (parts left out for brevity):
private int counter = 0;
@Override
public void visitIincInsn(int arg0, int arg1) {
super.visitIincInsn(arg0, arg1);
if (checkInstruction()) {
insertInstructions();
}
}
@Override
public void visitInsn(int arg0) {
super.visitInsn(arg0);
if (checkInstruction()) {
insertInstructions();
}
}
@Override
public void visitIntInsn(int arg0, int arg1) {
super.visitIntInsn(arg0, arg1);
if (checkInstruction()) {
insertInstructions();
}
}
/* And continue, implementing every method
which visits a specific type of instruction. */
private boolean checkInstruction() {
return counter++ == instructionNumber;
}
The problem I have with this solution is that it repeats a lot of code, and requires me to implement a bunch of methods whose purpose I have no intention of modifying. Plus, if new types of instructions are added, I would have to modify this code again just to implement that specific type of instruction.
Does anyone have a better solution?
Upvotes: 0
Views: 671
Reputation: 298233
Within ASM’s tree API you can find a utility class collecting all instructions which eases such a job:
import org.objectweb.asm.*;
import org.objectweb.asm.tree.*;
public class AsmFirstFiveOnly extends MethodVisitor {
private final MethodNode methodNode;
/** pass in the values provided in ClassVisitor.visitMethod */
public AsmFirstFiveOnly(
int access, String name, String desc, String signature, String[] exceptions){
this(new MethodNode(access, signature, signature, signature, exceptions));
}
private AsmFirstFiveOnly(MethodNode mn) {
super(Opcodes.ASM5, mn);
methodNode=mn;
}
// exemplary for the visit methods you are interested in,
// no need to override the others
@Override
public void visitInsn(int opcode) {
super.visitInsn(opcode);
if(methodNode.instructions.size()<5) {
// do your action
}
}
}
Upvotes: 2