使用ASM访问第n条指令

时间:2014-06-01 16:56:49

标签: java bytecode java-bytecode-asm

我需要编写将指令插入指定位置的方法的代码。我指定位置的方式是提供紧接在它之前的指令的编号。想法是访问所有指令,直到指令的编号等于指定的编号(因此第一条指令是第0条指令,下一条指令是第一条指令,等等),此时,我想要的指令注射将被注射。问题是没有通用的访问指令" MethodVisitor类中的方法;它只有访问特定类型指令的方法,所以我无法找到一种访问 nth 指令的优雅方式。这就是我提出的(为简洁起见省略的部分):

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;
}

我对这个解决方案的问题是它重复了很多代码,并且要求我实现一堆我无意修改的方法。另外,如果添加了新类型的指令,我将不得不再次修改此代码以实现该特定类型的指令。

有没有人有更好的解决方案?

1 个答案:

答案 0 :(得分:1)

在ASM的树API中,您可以找到一个实用程序类,收集所有简化此类工作的指令:

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

    }
  }
}