gpt4 book ai didi

java - 如何使用 ASM 更改静态变量值?

转载 作者:行者123 更新时间:2023-12-02 11:30:24 24 4
gpt4 key购买 nike

几天前我开始学习Java Agent。但文档不是很好,像我这样的初学者很难理解基础知识。我创建了一个基本的乘数类,并使用 eclipse 将其导出到可运行的 jar 中。这是代码片段。

主 jar 文件:

public class Multiplier {

public static void main(String[] args) {
int x = 10;
int y = 25;
int z = x * y;

System.out.println("Multiply of x*y = " + z);
}
}

Bytecode for above class

现在我想操纵代理的 x 值。我尝试创建像这样的 Agent 类

代理:

package myagent;

import org.objectweb.asm.*;
import java.lang.instrument.*;

public class Agent {

public static void premain(final String agentArg, final Instrumentation inst) {
System.out.println("Agent Started");
int x_modified = 5;

//Now How to push the new value (x_modified) to the multiplier class?
//I know I have to use ASM but can't figure it out how to do it.
//Result should be 125

}

}

我的问题

如何使用 ASM 将 x 的值从代理类设置为乘数类?结果应该是 125。

最佳答案

您的代理要做的第一件事是 registering a ClassFileTransformer 。类文件转换器应该在其 transform 方法中执行的第一件事是检查参数以查明当前请求是否与我们感兴趣的类有关,如果不是则立即返回。

如果我们处于要转换的类,我们必须处理传入的类文件字节以返回一个新的字节数组。您可以使用ASM的ClassReader处理传入字节并将其链接到 ClassWriter生成一个新数组:

import java.lang.instrument.*;
import java.security.ProtectionDomain;
import org.objectweb.asm.*;

public class ExampleAgent implements ClassFileTransformer {
private static final String TRANSFORM_CLASS = "Multiplier";
private static final String TRANSFORM_METHOD_NAME = "main";
private static final String TRANSFORM_METHOD_DESC = "([Ljava/lang/String;)V";

public static void premain(String arg, Instrumentation instrumentation) {
instrumentation.addTransformer(new ExampleAgent());
}

public byte[] transform(ClassLoader loader, String className, Class<?> cl,
ProtectionDomain pd, byte[] classfileBuffer) {
if(!TRANSFORM_CLASS.equals(className)) return null;

ClassReader cr = new ClassReader(classfileBuffer);
ClassWriter cw = new ClassWriter(cr, 0);
cr.accept(new ClassVisitor(Opcodes.ASM5, cw) {
@Override
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(
access, name, desc, signature, exceptions);
if(name.equals(TRANSFORM_METHOD_NAME)
&& desc.equals(TRANSFORM_METHOD_DESC)) {
return new MethodVisitor(Opcodes.ASM5, mv) {
@Override
public void visitIntInsn(int opcode, int operand) {
if(opcode == Opcodes.BIPUSH && operand == 10) operand = 5;
super.visitIntInsn(opcode, operand);
}
};
}
return mv;
}
}, 0);
return cw.toByteArray();
}
}

请注意,通过将 ClassWriter 传递给我们自定义的 ClassVisitor 的构造函数,并传递由 super.visitMethod 返回的 MethodVisitor 调用 MethodVisitor 的构造函数,我们启用默认情况下重现原始类的链接;我们没有重写的所有方法都将委托(delegate)给指定的 ClassWriter/MethodVisitor 来重现遇到的工件。与 the tutorial about ASM’s event model 比较.

上面的示例还通过将 ClassReader 实例传递给 ClassWriter 的构造函数来实现优化。这提高了在仅进行小更改时检测类的效率,就像我们在这里所做的那样。

关键部分是当我们处于“热门”方法时重写 visitMethod 以返回自定义 MethodVisitor 并重写 visitIntInsn 来更改所需的指导。请注意这些方法在不改变行为时如何委托(delegate)给 super 调用,就像我们没有重写的方法一样。

关于java - 如何使用 ASM 更改静态变量值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49334673/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com