Java?agent的入門與demo演示詳解
背景
繼之前我們研究了下skywalking是什么以及skywalking如何監(jiān)控skywalking
我們并沒有探討過多的skywalking原理 實(shí)際上skywalking的實(shí)現(xiàn)原理就是java的agent所以我們?cè)倮^續(xù)研究skywalking之前還是先補(bǔ)補(bǔ)基礎(chǔ)吧
什么是java 的agent
Java Agent 是 Java 1.5 版本之后引?的特性,其主要作?是在class被加載之前對(duì)其攔截,已插?我們的監(jiān)聽字節(jié)碼
官方文檔: https://docs.oracle.com/javase/8/docs/platform/jvmti/jvmti.html#whatIs
用通俗易懂的話來說就是,我們可以不改變?cè)许?xiàng)目的任何代碼,對(duì)項(xiàng)目進(jìn)行一些增強(qiáng)操作
agent的加載時(shí)機(jī)
Java的Agent加載時(shí)機(jī)分別有兩處
- 加載時(shí)刻增強(qiáng)(JVM 啟動(dòng)時(shí)加載)
- 動(dòng)態(tài)增強(qiáng)(JVM 運(yùn)行時(shí)加載)
我們要如何進(jìn)行編碼來實(shí)現(xiàn)我們的增強(qiáng)邏輯呢? JVM提供了幾個(gè)入口函數(shù)
加載時(shí)刻增強(qiáng)(JVM 啟動(dòng)時(shí)加載)
JVM 啟動(dòng)時(shí)加載啟動(dòng)時(shí)的入口方法提供了兩個(gè)
?//?方法一 public?static?void?premain(String?agentArgs,?Instrumentation?inst); //?方法二 public?static?void?premain(String?agentArgs);
這兩個(gè)函數(shù)的優(yōu)先級(jí)是,如果沒有方法一,則尋找方法二
動(dòng)態(tài)增強(qiáng)(JVM 運(yùn)行時(shí)加載)
JVM 運(yùn)行時(shí)加載也提供了兩個(gè)入口方法
//?方法一 public?static?void?agentmain(String?agentArgs,?Instrumentation?inst); //?方法二 public?static?void?agentmain(String?agentArgs);
與上面JVM 啟動(dòng)時(shí)加載的加載機(jī)制一樣。如果沒有方法一,則尋找方法二
如果剛接觸agent大家可能還是有點(diǎn)懵 沒關(guān)系,下面我們先帶大家寫一個(gè)簡單的demo來看看效果,這樣就更容易理解
demo演示
如果不想編寫我這里也提供了直接下載的源碼
源碼地址:https://github.com/weihubeats/weihubeats_demos/tree/master/java-demos/agent-demo
項(xiàng)目結(jié)構(gòu)

核心demo
package?com.weihubeats.agent.demo;
import?java.lang.instrument.Instrumentation;
public?class?AgentDemo?{
????public?static?void?premain(String?agentArgs,?Instrumentation?inst)?{
????????System.out.println("=========?小奏技術(shù)1?premain?init?========");
????????System.out.println("agentArgs:="+agentArgs);
????}
????
????public?static?void?premain(String?agentArgs)?{
????????System.out.println("=========?小奏技術(shù)2?premain?agentArgs?init?========");
????????System.out.println("agentArgs:="+agentArgs);
????}
????
}
注意我們寫完代碼之后需要?jiǎng)?chuàng)建一個(gè)resources/META-INF.MANIFEST.MF文件
文件內(nèi)容如下
Manifest-Version: 1.0
Can-Redefine-Classes: true # true表示能重定義此代理所需的類,默認(rèn)值為 false(可選)
Can-Retransform-Classes: true # true 表示能重轉(zhuǎn)換此代理所需的類,默認(rèn)值為 false (可選)
Premain-Class: com.weihubeats.agent.demo.AgentDemo
這樣我們的代碼就編寫完成了。這時(shí)候我們需要將整個(gè)項(xiàng)目打成一個(gè)jar,然后給其他項(xiàng)目接入
需要注意如果我們要測試agentmain的使用,需要手動(dòng)調(diào)用觸發(fā)
import?com.sun.tools.attach.VirtualMachine;
public?class?Main?{
??public?static?void?main(String[]?args)?{
????//?獲取當(dāng)前?Java?進(jìn)程的?PID
????String?pid?=?ManagementFactory.getRuntimeMXBean().getName().split("@")[0];?
????
????//?使用運(yùn)行中的?JVM?PID?創(chuàng)建一個(gè)?VirtualMachine?對(duì)象
????VirtualMachine?vm?=?VirtualMachine.attach(pid);
????
????//?加載并附加?Java?Agent?到運(yùn)行中的?JVM
????vm.loadAgent("path/to/your/agent.jar");
????
????//?現(xiàn)在?agentmain?方法應(yīng)該已經(jīng)被調(diào)用了
??}
}
從這里可以看到agentmain的增強(qiáng)方式觸發(fā)有點(diǎn)麻煩,所以我們就暫>時(shí)不演示這種觸發(fā)方式了 skywalking的實(shí)現(xiàn)也是基于premain去實(shí)現(xiàn)的

打包
pom添加打包插件
<build> ????????<finalName>java-agent-demo</finalName> ????????<plugins> ????????????<plugin> ????????????????<artifactId>maven-shade-plugin</artifactId> ????????????????<executions> ????????????????????<execution> ????????????????????????<phase>package</phase> ????????????????????????<goals> ????????????????????????????<goal>shade</goal> ????????????????????????</goals> ????????????????????????<configuration> ????????????????????????????<shadedArtifactAttached>false</shadedArtifactAttached> ????????????????????????????<createDependencyReducedPom>true</createDependencyReducedPom> ????????????????????????????<createSourcesJar>true</createSourcesJar> ????????????????????????????<shadeSourcesContent>true</shadeSourcesContent> ????????????????????????????<transformers> ????????????????????????????????<transformer ????????????????????????????????????implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> ????????????????????????????????????<manifestEntries> ????????????????????????????????????????<Premain-Class>com.weihubeats.agent.demo.AgentDemo</Premain-Class> ????????????????????????????????????????<Can-Redefine-Classes>true</Can-Redefine-Classes> ????????????????????????????????????????<Can-Retransform-Classes>true</Can-Retransform-Classes> ????????????????????????????????????</manifestEntries> ????????????????????????????????</transformer> ????????????????????????????</transformers> ????????????????????????????<!--<artifactSet> ????????????????????????????????<excludes> ????????????????????????????????????<exclude>*:gson</exclude> ????????????????????????????????????<exclude>io.netty:*</exclude> ????????????????????????????????????<exclude>io.opencensus:*</exclude> ????????????????????????????????????<exclude>com.google.*:*</exclude> ????????????????????????????????????<exclude>com.google.guava:guava</exclude> ????????????????????????????????????<exclude>org.checkerframework:checker-compat-qual</exclude> ????????????????????????????????????<exclude>org.codehaus.mojo:animal-sniffer-annotations</exclude> ????????????????????????????????????<exclude>io.perfmark:*</exclude> ????????????????????????????????????<exclude>org.slf4j:*</exclude> ????????????????????????????????</excludes> ????????????????????????????????<!–?將javassist包打包到Agent中?–> ????????????????????????????????<includes> ????????????????????????????????????<include>javassist:javassist:jar:</include> ????????????????????????????????</includes> ????????????????????????????</artifactSet>--> ????????????????????????????<filters> ????????????????????????????????<filter> ????????????????????????????????????<artifact>net.bytebuddy:byte-buddy</artifact> ????????????????????????????????????<excludes> ????????????????????????????????????????<exclude>META-INF/versions/9/module-info.class</exclude> ????????????????????????????????????</excludes> ????????????????????????????????</filter> ????????????????????????????</filters> ????????????????????????</configuration> ????????????????????</execution> ????????????????</executions> ????????????</plugin> ????????</plugins> ????</build>
打包方式很簡單,我們?cè)陧?xiàng)目根目錄執(zhí)行打包命令
mvn clean package

打完包后我們的項(xiàng)目target目錄出現(xiàn)了我們的agent

spring boot 項(xiàng)目接入
我們?cè)?code>spring boot項(xiàng)目添加如下啟動(dòng)參數(shù)
-javaagent:/Users/weihu/Desktop/sofe/java/weihubeats_demos/java-demos/agent-demo/target/java-agent-demo.jar=xiaozouParam=xiaozou
然后我們啟動(dòng)參數(shù),查看log

可以看到啟動(dòng)成功了
總結(jié)
java agent的增強(qiáng)主要用兩種方式agentmain和premain大多應(yīng)用程序應(yīng)該是使用的premain,因?yàn)榭梢钥吹?code>agentmain還需要應(yīng)用系統(tǒng)自己添加代碼去觸發(fā)
agent的一些基礎(chǔ)方法和接入使用,其實(shí)agent的字節(jié)碼編程開發(fā)才是最麻煩的。 后續(xù)我們也會(huì)學(xué)習(xí)字節(jié)碼編程
以上就是Java agent的入門與demo演示詳解的詳細(xì)內(nèi)容,更多關(guān)于Java agent的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用springboot結(jié)合vue實(shí)現(xiàn)sso單點(diǎn)登錄
這篇文章主要為大家詳細(xì)介紹了如何使用springboot+vue實(shí)現(xiàn)sso單點(diǎn)登錄,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-06-06
詳解Spring Boot使用系統(tǒng)參數(shù)表提升系統(tǒng)的靈活性
Spring Boot項(xiàng)目中常有一些相對(duì)穩(wěn)定的參數(shù)設(shè)置項(xiàng),其作用范圍是系統(tǒng)級(jí)的或模塊級(jí)的,這些參數(shù)稱為系統(tǒng)參數(shù)。這些變量以參數(shù)形式進(jìn)行配置,從而提高變動(dòng)和擴(kuò)展的靈活性,保持代碼的穩(wěn)定性2021-06-06
Spring-cloud 服務(wù)發(fā)現(xiàn)與消費(fèi)(以ribbon為例)
這篇文章主要介紹了Spring-cloud 服務(wù)發(fā)現(xiàn)與消費(fèi)(以ribbon為例),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-04-04
用Java代碼實(shí)現(xiàn)一幅春聯(lián)詳解
大家好,本篇文章主要講的是用Java代碼實(shí)現(xiàn)一幅春聯(lián)詳解,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽2022-01-01
springboot結(jié)合前端實(shí)現(xiàn)網(wǎng)頁跳轉(zhuǎn)功能實(shí)例
今天處理Springboot統(tǒng)一異常攔截的時(shí)候,遇到了頁面跳轉(zhuǎn)的問題,這篇文章主要給大家介紹了關(guān)于springboot結(jié)合前端實(shí)現(xiàn)網(wǎng)頁跳轉(zhuǎn)功能的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12

