java agent 詳細介紹
簡介
java agent是java命令的一個參數。參數 javaagent 可以用於指定一個 jar 包,並且對該 java 包有2個要求:
- 這個 jar 包的MANIFEST.MF 文件必須指定 Premain-Class 項。
- 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 類中:
如何使用
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包名 啟動要代理的方法。
和類加載器比較
類加載器也可以實現運行時修改代碼。但是對代碼的侵入性很高。使用 java agent 能讓修改字節碼這個動作化於無形,對業務透明,減少侵入性。
agent的缺點
需要設置參數javaagent