我已经开始学习(我是新手),编译器项目的ASM API。我正在使用java Instrumentation和ASM ByteCode Library来开发Javaagent。
我通过属性传递类名和方法名。我的目标是在运行时更改我的className和methodName(意味着在服务器启动或调用premain()之后)。
但是,它仅适用于在启动服务器之前传递的className或packageName。
据我所知,在调用javaagent(premain())时,ASM为给定pakage / class的方法设置了访问者。
即使在服务器启动或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);
}
}
}
提前致谢
Sathish V J
答案 0 :(得分:0)
您应该清理代码。在premain
方法中,您将属性文件加载到Properties
对象中,但该实例从未使用过。而是在每次Properties
调用时将该文件重新加载到另一个visitEnd()
实例中。我不确定这是否真的是你想要的。
但是,在类加载期间调用变换器,但是对于已经加载的类不调用。您可以尝试重新转换或重新定义加载的类,但是加载后更改类或方法名称不受检测支持。