我正在尝试一种检测死代码并使用 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])
永远不会被触及。我不知道原因,因为我们对该方法有一个无法访问的声明。你们看到这种方法有什么问题吗?