日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java字节码提取if语句_java – 使用ASM选择和修改`if`语句

發(fā)布時間:2025/3/20 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java字节码提取if语句_java – 使用ASM选择和修改`if`语句 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

問題1可能是最困難的.您需要通過識別某些模式來找出插入指令的位置.如果您假設(shè)firstPar.check()只被調(diào)用一次,那么您可以查找if(firstPar.check())的以下字節(jié)碼指令:

ALOAD 1

INVOKEVIRTUAL Data.check ()Z

IFEQ L3

其中L3是跳轉(zhuǎn)標(biāo)簽,如果檢查返回false.

對于問題2,請注意if(firstPar.check()&&!Utilities.someOtherCheck(firstPar,secondPar))的字節(jié)碼指令是:

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執(zhí)行此操作,您可以通過繼承ClassVisitor和MethodNode為targetMethod創(chuàng)建適配器:

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以迭代方法內(nèi)的所有指令,并嘗試檢測上述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對其進(jìn)行鏈接.下面,我還鏈接一個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

總結(jié)

以上是生活随笔為你收集整理的java字节码提取if语句_java – 使用ASM选择和修改`if`语句的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。