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

ASM字节码操作:检测与插入指令
这篇博客详细介绍了如何使用ASM库在Java字节码级别进行操作,特别是针对`firstPar.check()`和`Utilities.someOtherCheck(firstPar, secondPar)`的条件判断。内容包括如何识别特定字节码指令模式,以及在找到这些模式后如何插入新的字节码指令。文章还提供了一个ClassAdapter和MethodAdapter的示例,用于在目标方法中定位并插入新指令。
部署运行你感兴趣的模型镜像

问题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

您可能感兴趣的与本文相关的镜像

Langchain-Chatchat

Langchain-Chatchat

AI应用
Langchain

Langchain-Chatchat 是一个基于 ChatGLM 等大语言模型和 Langchain 应用框架实现的开源项目,旨在构建一个可以离线部署的本地知识库问答系统。它通过检索增强生成 (RAG) 的方法,让用户能够以自然语言与本地文件、数据库或搜索引擎进行交互,并支持多种大模型和向量数据库的集成,以及提供 WebUI 和 API 服务

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值