JavaAgent 是JDK 1.5 以後引入的,也可以叫做Java代理。
JavaAgent 是運行在 main方法之前的攔截器,它內定的方法名叫 premain ,也就是說先執行 premain 方法然後再執行 main 方法。
那麼如何實現一個 JavaAgent 呢?很簡單,只需要增加 premain 方法即可,後續可以在此基礎上實現注入攔截,AOP等。
package com.xifj.agent.demo;
import java.lang.instrument.Instrumentation;
/**
* Created by uc on 2018/4/18.
*/
public class agentDemo {
/**
* 該方法在main方法之前運行,與main方法運行在同一個JVM中
*
* @param agentArgs
* @param inst
* @author xifeijian
* @create 2018年4月18日
*/
public static void premain(String agentArgs, Instrumentation inst) {
System.out.println("=========premain方法執行1========");
System.out.println(agentArgs);
}
/**
* 如果不存在 premain(String agentArgs, Instrumentation inst)
* 則會執行 premain(String agentArgs)
*
* @param agentArgs
* @author xifeijian
* @create 2018年4月18日
*/
public static void premain(String agentArgs) {
System.out.println("=========premain方法執行2========");
System.out.println(agentArgs);
}
}
在這個 premain 函數中,開發者可以進行對類的各種操作。
1、agentArgs 是 premain 函數得到的程序參數,隨同 “– javaagent”一起傳入。與 main 函數不同的是,這個參數是一個字符串而不是一個字符串數組,如果程序參數有多個,程序將自行解析這個字符串。
2、Inst 是一個 java.lang.instrument.Instrumentation 的實例,由 JVM 自動傳入。java.lang.instrument.Instrumentation 是 instrument 包中定義的一個接口,也是這個包的核心部分,集中了其中幾乎所有的功能方法,例如類定義的轉換和操作等等。
寫完這個類後,我們還需要做一步配置工作,在 src 目錄下生成 META-INF/MANIFEST.MF 文件。
然後編輯META-INF/MANIFEST.MF,內容按如下定義:
要特別注意,最後一行是空行,還有就是Premain-Class冒號後面有個空格,例如:
Manifest-Version: 1.0
Premain-Class: com.xifj.agent.demo.agentDemo
然後我們打包代碼爲 javaagent.jar(Build-Artifact)
接着我們在創建一個帶有main方法的主程序工程,截圖如下:
工程代碼已完成,運行前配置VM參數:
-javaagent:D:\workspace\javaagent\out\artifacts\javaagent_jar\javaagent.jar=Hello -javaagent:D:\workspace\javaagent\out\artifacts\javaagent_jar\javaagent.jar=World
運行agentTest程序,得到以下結果:
也可以將agentTest打成jar包通過java命令行執行,我們通過 -javaagent 參數來指定我們的Java代理包,值得一說的是 -javaagent 這個參數的個數是不限的,如果指定了多個,則會按指定的先後執行,執行完各個 agent 後,纔會執行主程序的 main 方法。命令如下:
java -javaagent:D:\workspace\javaagent\out\artifacts\javaagent_jar\javaagent.jar=hello1 -javaagent:D:\workspace\javaagent\out\artifacts\javaagent_jar\javaagent.jar=hello2 -jar D:\workspace\myTest\out\artifacts\myTest_jar\myTest.jar
執行結果和上圖是完全一致的。
特別提醒:如果你把 -javaagent 放在 -jar 後面,則不會生效。也就是說,放在主程序後面的 agent 是無效的。