不知道javaagent是什么?運行個hello world就知道了


從事java開發的同學,或多或少聽說過java探針/javaagent這個術語。本文不說它的定義,不說它的原理,不說它的高大上的作用,只說它的"hello world"。即運行一個最簡單的例子,實際看看效果,真切的感受后,才能真切清晰的入口。

編碼

用idea創建個maven項目,如下圖,項目名稱隨意,這里我的項目名為:microservice-comb-javaagent

20200310194628.png

 

代碼如下 首先,創建一個類:AgentDemo

public class AgentDemo {
    /**
     * 該方法在main方法之前運行,與main方法運行在同一個JVM中
     */
    public static void premain(String agentArgs, Instrumentation inst) {
        System.out.println("------ premain方法 有兩個入參 ------ agentArgs:" + agentArgs + " inst:" + inst.toString()); } /** * 如果不存在 {@link AgentDemo#premain(String, Instrumentation)}, 則會執行本方法 */ public static void premain(String agentArgs) { System.out.println("------ premain方法,有一個入參 ------ agentArgs:" + agentArgs); } } 復制代碼

注意:AgentDemo的全限定名會在pom.xml中標簽Premain-Class引用

其次,再創建一個類:AgentTest

public class AgentTest {
    public static void main(String[] args) {
        System.out.println(" ------ main方法"); } } 復制代碼

再次,在項目的pom.xml中添加

   ··· 略

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <manifestEntries> <!-- 值為包含premain方法的類. 啟動方式為命令行啟動時,javaagent JAR文件清單必須包含 Premain-Class 屬性, 代理類必須實現 public static premain()--> <Premain-Class>com.skyler.cobweb.agent.AgentDemo</Premain-Class> <Can-Redefine-Classes>true</Can-Redefine-Classes> <Can-Retransform-Classes>true</Can-Retransform-Classes> </manifestEntries> </archive> </configuration> </plugin> </plugins> </build> 復制代碼

打jar包

microservice-comb-javaagent打成jar包。運行時會使用這個Jar包.打包命令:mvn clean package。結果如下圖

 

運行

你可以有兩個運行方式:idea中直接運行命令行運行

  • idea中直接運行

需要配置下項目的運行配置的VM options,如下圖,形式為-javaagent:jarpath[=options]; 我的內容為:-javaagent:/Users/xx/microservice-comb/microservice-comb-javaagent/target/microservice-comb-javaagent-1.0.0-SNAPSHOT.ar="hello world"

 

20200310211044.png

 

然后,運行AgentTest.main方法,結果如下圖

20200310201519.png

 

可以看到,打印出了AgentDemo.premain方法的信息

  • 命令行運行 cd到項目microservice-comb-javaagent的/target/classes路徑下
$ cd xx/target/classes $ java -javaagent:/Users/xx/microservice-comb/microservice-comb-javaagent/target/microservice-comb-javaagent-1.0.0-SNAPSHOT.jar="hello world" com.skyler.cobweb.agent.AgentTest 復制代碼

可以看到,同樣打印出了AgentDemo.premain方法的信息

20200310203649.png

 

收獲

這里有個對比,運行時是否加上-javaagent:jar,這個給你的感受會很明顯和透徹。來再操作下

加上時

$ cd /Users/xx/microservice-comb/microservice-comb-javaagent/target/classes $ java -javaagent:/Users/xx/microservice-comb/microservice-comb-javaagent/target/microservice-comb-javaagent-1.0.0-SNAPSHOT.jar="hello world" com.skyler.cobweb.agent.AgentTest 復制代碼

效果

------ premain方法 有兩個入參 ------ agentArgs:hello world inst:sun.instrument.InstrumentationImpl@a09ee92
 ------ main方法
復制代碼

不加上時

$ cd /Users/xx/microservice-comb/microservice-comb-javaagent/target/classes $ java com.skyler.cobweb.agent.AgentTest 復制代碼

效果

 ------ main方法

復制代碼

效果還是很明顯的,不加-javaagent,jar里的類方法沒有執行,也即不會輸出信息

這個對比的目的是突出javaagent的作用。並讓你清晰的感受javaagent的作用:像代理一樣可以在main方法前做些事情,官方的說字節碼增強。通過修改字節碼的方式,讓開發者有機會做些事情,如arthas 和skywalking的建監聽組件

千言萬語抵不上run一個'hello world'

本文想通過最簡單、最直觀的方式,讓你最快速的、最真切的了解javaagent的作用。下篇展開說javaagent的原理和更實際的使用例子


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM