0

私は学習を始めました(これは初めてです)、コンパイラプロジェクトのASM APIです。Javaagent の開発に Java Instrumentation と ASM ByteCode Library を使用しています。

プロパティを介してクラス名とメソッド名を渡しています。私の目標は、実行時にclassNameとmethodNameを変更することです(サーバーの起動後または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 に答える