0

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

4

1 回答 1

0

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

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

于 2013-11-07T12:07:12.137 回答