簡體   English   中英

Java字節碼檢測代理問題

[英]Problems with Java Agent for Bytecode Instrumentation

這是我第一次實現Java代理,並嘗試學習有關字節碼檢測的知識。 閱讀了幾篇介紹和教程后,我編寫了一個帶有兩個類(夏季和應用程序)的小型應用程序。 現在我想通過premain方法運行一個Java代理以使用以下代碼顯示執行路徑:

public class TestJavaAgent {
    public static void premain(String agentArgument,
                               Instrumentation instrumentation){
        instrumentation.addTransformer(new ClassFileTransformer() {

            @Override
            public byte[] transform(ClassLoader classLoader, String s, Class<?> aClass, ProtectionDomain protectionDomain, byte[] bytes) throws IllegalClassFormatException {

                ClassPool cp = ClassPool.getDefault();
                    try {
                        CtClass cc = cp.get("Summer");
                        CtMethod methods [] = cc.getMethods();

                        for( CtMethod method : methods){
                            System.out.println("Entering "+method.getName());
                            method.addLocalVariable("elapsedTime", CtClass.longType);
                            method.insertBefore("elapsedTime = System.currentTimeMillis();");
                            method.insertAfter("{elapsedTime = System.currentTimeMillis() - elapsedTime;"
                                    + "System.out.println(\"Method Executed in ms: \" + elapsedTime);}");
                        }
                        return cc.toBytecode();

                    } catch (Exception ex) {
                        return bytes;
                    }
            }
        });
    }
}

我通過java -javaagent{Agent JAR} -jar {Application Jar}啟動了代理,但是它沒有顯示任何插入的消息。 調試代碼后,我意識到“ ClassPool.getDefault()”之后的所有內容都無法實現,但我不知道為什么。 有人能幫我嗎?

轉換器應該轉換作為參數傳遞的類,而不是您喜歡的任意類。 注冊后,將為所有已加載的類(包括您自己使用的類)(第一個是ClassPool )調用此ClassPool 因此,您正在創建循環依賴項。

您必須檢查類名參數,然后等待直到要轉​​換的類的方法被調用為止。 對於所有其他類,只需返回null

public class TestJavaAgent {
    public static void premain(String agentArgument, Instrumentation instrumentation) {
        instrumentation.addTransformer(new ClassFileTransformer() {

            @Override
            public byte[] transform(ClassLoader classLoader,
                String className, Class<?> aClass, ProtectionDomain protectionDomain, byte[] bytes) throws IllegalClassFormatException {

                if(!className.equals("Summer")) return null;

                ClassPool cp = ClassPool.getDefault();
                try {
                    // use the class bytes your received as parameter
                    cp.insertClassPath(new ByteArrayClassPath(className, bytes));

                    CtClass cc = cp.get("Summer");
                    CtMethod[] methods = cc.getMethods();

                    for( CtMethod method : methods){
                        System.out.println("Entering "+method.getName());
                        method.addLocalVariable("elapsedTime", CtClass.longType);
                        method.insertBefore("elapsedTime = System.currentTimeMillis();");
                        method.insertAfter("{elapsedTime = System.currentTimeMillis() - elapsedTime;"
                                + "System.out.println(\"Method Executed in ms: \" + elapsedTime);}");
                    }
                    return cc.toBytecode();

                } catch (Exception ex) {
                    return null;
                }
            }
        });
    }
}

請注意,如果您不進行任何更改,則返回null勝於返回原始數組,因為JVM可以立即識別出您沒有進行任何更改,而無需查看數組內容。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM