ASM访客删除无法访问的代码

时间:2016-09-23 13:54:26

标签: bytecode java-bytecode-asm jvm-bytecode

我正试图找到一种检测死代码的方法,并使用ASM将其从字节码中删除。 我正在关注ASM 4 Guide,并在第119页中声明了一个死代码删除访问者:

public class RemoveDeadCodeAdapter extends MethodVisitor {
  String owner;
  MethodVisitor next;
  public RemoveDeadCodeAdapter(String owner, int access, String name,
      String desc, MethodVisitor mv) {
    super(Opcodes.ASM4, new MethodNode(access, name, desc, null, null));
    this.owner = owner;
    next = mv;
  }
  @Override public void visitEnd() {
    MethodNode mn = (MethodNode) mv;
    Analyzer<BasicValue> a =
        new Analyzer<BasicValue>(new BasicInterpreter());
    try {
      a.analyze(owner, mn);
      Frame<BasicValue>[] frames = a.getFrames();
      AbstractInsnNode[] insns = mn.instructions.toArray();
      for (int i = 0; i < frames.length; ++i) {
        if (frames[i] == null && !(insns[i] instanceof LabelNode)) {
          mn.instructions.remove(insns[i]);
        }
      }
    } catch (AnalyzerException ignored) {
    }
    mn.accept(next);
  }
}

此外,我正在尝试使用以下代码调用此访问者:

public class RunDeadCodeAdapter {

  public static void main(String ... args) throws Exception {
    ClassVisitor cv = new ClassVisitor(Opcodes.ASM4) {

      String owner;

      @Override
      public void visit(int version, int access, String name, String signature, String superName,
          String[] interfaces) {
        owner = name;
      }

      @Override
      public MethodVisitor visitMethod(int access, String name, String desc, String signature,
          String[] exceptions) {
        TraceMethodVisitor tmv = new TraceMethodVisitor(null, new Textifier());
        return new RemoveDeadCodeAdapter(owner, access, name, desc, tmv);
      }
    };
    ClassReader cr = new ClassReader("com/mypackage/locator/DeadClass");
    cr.accept(cv, 0);
  }
}

我正在使用的代码示例是:

public boolean myDeadStatementsMethod(){
    int x = 10;
    if (true){
      x += 20;
      System.out.println(x);
      return true;
    } else {
      throw new RuntimeException("true is not true");
    }
  }

理论上,行throw new RuntimeException("true is not true");可以被视为无法访问的代码,因为它永远不会被执行。这种方法的问题是语句mn.instructions.remove(insns[i])永远不会被触及。我不知道原因,因为我们对该方法有一个无法访问的声明。你们看到这种方法有什么问题吗?

0 个答案:

没有答案