java字节码提取if语句_java – 使用ASM选择和修改`if`语句
問題1可能是最困難的.您需要通過識別某些模式來找出插入指令的位置.如果您假設firstPar.check()只被調用一次,那么您可以查找if(firstPar.check())的以下字節碼指令:
ALOAD 1
INVOKEVIRTUAL Data.check ()Z
IFEQ L3
其中L3是跳轉標簽,如果檢查返回false.
對于問題2,請注意if(firstPar.check()&&!Utilities.someOtherCheck(firstPar,secondPar))的字節碼指令是:
ALOAD 1
INVOKEVIRTUAL Data.check ()Z
IFEQ L3
ALOAD 1
ALOAD 2
INVOKESTATIC Utilities.someOtherCheck (LData;LData;)Z
IFNE L3
因此,您需要在IFEQ L3之后插入4條新指令.
您可以使用Tree API執行此操作,您可以通過繼承ClassVisitor和MethodNode為targetMethod創建適配器:
private static class ClassAdapter extends ClassVisitor {
public ClassAdapter(ClassVisitor cv) {
super(Opcodes.ASM5, cv);
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);
if (name.equals("targetMethod"))
return new MethodAdapter(access, name, desc, signature, exceptions, mv);
else
return mv;
}
}
private static class MethodAdapter extends MethodNode {
public MethodAdapter(int access, String name, String desc,
String signature, String[] exceptions, MethodVisitor mv) {
super(Opcodes.ASM5, access, name, desc, signature, exceptions);
this.mv = mv;
}
// More to come ...
}
在MethodAdapter中,您可以覆蓋visitEnd以迭代方法內的所有指令,并嘗試檢測上述3條指令并在其后插入4條新指令:
@Override
public void visitEnd() {
// Iterates all instructions in the method
ListIterator itr = instructions.iterator();
while (itr.hasNext()) {
// Checks whether the instruction is ALOAD 1
AbstractInsnNode node = itr.next();
if (node.getOpcode() != Opcodes.ALOAD
|| ((VarInsnNode) node).var != 1)
continue;
// Checks whether the next instruction is INVOKEVIRTUAL
if (node.getNext() == null
|| node.getNext().getOpcode() != Opcodes.INVOKEVIRTUAL)
continue;
// Checks the invoked method name and signature
MethodInsnNode next = (MethodInsnNode) node.getNext();
if (!next.owner.equals("Data")
|| !next.name.equals("check")
|| !next.desc.equals("()Z"))
continue;
// Checks whether the next of the next instruction is IFEQ
AbstractInsnNode next2 = next.getNext();
if (next2 == null
|| next2.getOpcode() != Opcodes.IFEQ)
continue;
// Creates a list instructions to be inserted
InsnList list = new InsnList();
list.add(new VarInsnNode(Opcodes.ALOAD, 1));
list.add(new VarInsnNode(Opcodes.ALOAD, 2));
list.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
"Utilities", "someOtherCheck",
"(LData;LData;)Z", false));
list.add(new JumpInsnNode(Opcodes.IFNE, ((JumpInsnNode) next2).label));
// Inserts the list, updates maxStack to at least 2, and we are done
instructions.insert(next2, list);
maxStack = Math.max(2, maxStack);
break;
}
accept(mv);
}
要使用適配器,可以使用ClassReader和ClassWriter對其進行鏈接.下面,我還鏈接一個TraceClassVisitor來打印tmp目錄中的日志文件:
ClassReader reader = new ClassReader("Target");
ClassWriter writer = new ClassWriter(reader, 0);
TraceClassVisitor printer = new TraceClassVisitor(writer,
new PrintWriter(System.getProperty("java.io.tmpdir") + File.separator + "Target.log"));
ClassAdapter adapter = new ClassAdapter(printer);
reader.accept(adapter, 0);
byte[] b = writer.toByteArray(); // The modified bytecode
總結
以上是生活随笔為你收集整理的java字节码提取if语句_java – 使用ASM选择和修改`if`语句的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python如何下载zip文件_使用py
- 下一篇: php switch 函数,PHP丨PH