启动服务器后,我可以在运行时将className和methodName传递给ASM解析器中的ClassVisitor()和methodVisitor()吗?

时间:2013-07-09 13:43:02

标签: java compilation bytecode java-bytecode-asm

我已经开始学习(我是新手),编译器项目的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

1 个答案:

答案 0 :(得分:0)

您应该清理代码。在premain方法中,您将属性文件加载到Properties对象中,但该实例从未使用过。而是在每次Properties调用时将该文件重新加载到另一个visitEnd()实例中。我不确定这是否真的是你想要的。

但是,在类加载期间调用变换器,但是对于已经加载的类不调用。您可以尝试重新转换或重新定义加载的类,但是加载后更改类或方法名称不受检测支持。