我已经开始学习(我是新手),用于编译器项目的 ASM API。我正在使用 java Instrumentation 和 ASM ByteCode Library 来开发 Javaagent。
我通过属性传递类名和方法名。我的目标是在运行时更改我的类名和方法名(意味着在服务器启动或调用 premain() 之后)。
但是,它仅适用于在启动服务器之前传递的 className 或 packageName。
我知道,在调用 javaagent ( premain() ) 时,ASM 为给定包/类的方法设置访问者。
即使在服务器启动或调用 premain() 之后,我也想访问特定的类和方法。
如果有人对此有所帮助,那将非常有帮助。
这是我目前正在运行的程序。
public class AddPrintlnAgent implements ClassFileTransformer {
public static void premain(String agentArgs, Instrumentation inst) {
Properties prop = new Properties();
try {
prop.load(new FileInputStream("C:\\locator.properties"));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
inst.addTransformer(new AddPrintlnAgent());
}
public byte[] transform(ClassLoader loader, String className,
Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
byte[] classfileBuffer) throws IllegalClassFormatException {
byte[] retVal = null;
if (className.equals(className)) {
ClassWriter cw = new ClassWriter(0);
ClassVisitor ca = new MyClassAdapter(cw);
ClassReader cr = new ClassReader(classfileBuffer);
cr.accept(ca, 0);
retVal = cw.toByteArray();
}
return retVal;
}
public class MyClassAdapter extends ClassNode implements Opcodes {
private ClassVisitor cv;
Properties prop = new Properties();
public MyClassAdapter(ClassVisitor cv) {
this.cv = cv;
}
@Override
public void visitEnd() {
try {
prop.load(new FileInputStream("C:\\locator.properties"));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
for (MethodNode mn : (List<MethodNode>) methods) {
if (mn.name.equals(prop.getProperty("methodName").trim())) {
InsnList il = new InsnList();
il.add(new FieldInsnNode(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"));
il.add(new LdcInsnNode(prop.getProperty("message")));
il.add(new MethodInsnNode(INVOKEVIRTUAL, "java/io/PrintStream",
"println", "(Ljava/lang/String;)V"));
mn.instructions.insert(il);
mn.maxStack +=2;
}
}
accept(cv);
}
}
}
提前致谢
萨蒂什 VJ