java agent 詳細介紹

什麼是 javaagent

java agent是java命令的一個參數。參數 javaagent 可以用於指定一個 jar 包,並且對該 java 包有2個要求:

  1. 這個 jar 包的MANIFEST.MF 文件必須指定 Premain-Class 項。
  2. Premain-Class 指定的那個類必須實現 premain()方法。

重點就在 premain 方法,也就是我們今天的標題。從字面上理解,就是運行在 main 函數之前的的類。當Java 虛擬機啓動時,在執行 main 函數之前,JVM 會先運行 -javaagent 所指定 jar 包內 Premain-Class 這個類的 premain 方法,其中,該方法可以簽名如下:

1.public static void premain(String agentArgs, Instrumentation inst)
2.public static void premain(String agentArgs)

JVM 會優先加載 1 簽名的方法,加載成功忽略 2,如果1 沒有,加載 2 方法。這個邏輯在sun.instrument.InstrumentationImpl 類中:

clipboard.png

如何使用

1 首先定義一個 MANIFEST.MF 文件:

Manifest-Version: 1.0
Can-Redefine-Classes: true
Can-Retransform-Classes: true
Premain-Class: cn.think.in.java.clazz.loader.asm.agent.PreMainTraceAgent

創建一個Premain-Class 指定的類,類中包含 premain 方法:

public class Main {

    public static void premain(String agentArgs, Instrumentation inst) {
        System.out.println("agentArgs : " + agentArgs);
        inst.addTransformer(new ClassFileTransformer() {
            @Override
            public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
                                    ProtectionDomain protectionDomain, byte[] classfileBuffer)
                    throws IllegalClassFormatException {
                System.out.println("premain load Class     :" + className);
                return classfileBuffer;
            }
        }, true);
    }
}

將 premain 的類和 MANIFEST.MF 文件打成 jar 包 .
使用 IDEA 的 build ,當然你也可以使用 maven
再簡單創建一個test類

public class AccountMain {
  public static void main(String[] args)
        throws ClassNotFoundException, InterruptedException, IllegalAccessException, InstantiationException, NoSuchMethodException,
               InvocationTargetException {
    System.out.println("11111111111");
  }
}

}
使用參數 -javaagent:jar包名 啓動要代理的方法。

clipboard.png

和類加載器比較

類加載器也可以實現運行時修改代碼。但是對代碼的侵入性很高。使用 java agent 能讓修改字節碼這個動作化於無形,對業務透明,減少侵入性。

agent的缺點

需要設置參數javaagent

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章