APM - Hello Javaagent
文章目錄
- 什么是javaagent
- javaagent的jar包 和 普通jar包的區(qū)別
- 從零搭建第一個javaagent
- 【pom.xml】
- 【Agent Code】
- 【編譯成jar】
- 【引入agent jar 為當(dāng)前應(yīng)用啟動前插入premain邏輯】
- javaagent 流程示意圖
- 進階Demo
- Javassist 引入
什么是javaagent
簡單來說, javaagent 是在class 被裝在到ClassLoader之前對其攔截,插入自定義的監(jiān)聽字節(jié)碼,可實現(xiàn)零侵入的監(jiān)控,是APM的核心技術(shù)
Java1.5之后引入的特性
JavaAgent 運行在 main方法之前 ,內(nèi)置的方法名為premain,即先執(zhí)行premain方法,然后再執(zhí)行main方法。通過premain方法,可實現(xiàn)一個JavaAgent。
javaagent 應(yīng)用場景:監(jiān)控、代碼覆蓋率分析 、JProfiler、應(yīng)用破解等等等
javaagent的jar包 和 普通jar包的區(qū)別
javaagent 其實就是一個jar 包,通過-javaagent:xxx.jar 引入監(jiān)控目標(biāo)應(yīng)用。那這個jar 和普通的jar 的區(qū)別在哪里呢?
我們來先看個結(jié)論
從零搭建第一個javaagent
maven搭建 編譯
【pom.xml】
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.artisan</groupId><artifactId>javaagent</artifactId><version>1.0-SNAPSHOT</version><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>2.2</version><configuration><archive><manifestEntries><Project-name>${project.name}</Project-name><Project-version>${project.version}</Project-version><Premain-Class>com.artisan.ssist.JavaAgentDemo</Premain-Class><Boot-Class-Path>javassist-3.18.1-GA.jar</Boot-Class-Path><Can-Redefine-Classes>false</Can-Redefine-Classes></manifestEntries></archive><skip>true</skip></configuration></plugin></plugins></build><dependencies><dependency><groupId>org.javassist</groupId><artifactId>javassist</artifactId><version>3.18.1-GA</version></dependency></dependencies></project>- Premain-Class:指定包含 premain 方法的類名 ,改成自己的類
- Can-Redefine-Class:是否能重新定義此代理所需的類,默認(rèn)為 false。
【Agent Code】
package com.artisan.ssist;import java.lang.instrument.Instrumentation;public class JavaAgentDemo {public static void premain(String args ,Instrumentation instrumentation){System.out.println("premain first agent demo");} }【編譯成jar】
點擊 M, 執(zhí)行 mvn clean package
查看jar包中的 MANIFEST.MF文件 , MANIFEST.MF文件用于描述Jar包的信息,例如指定入口函數(shù)等。
【引入agent jar 為當(dāng)前應(yīng)用啟動前插入premain邏輯】
jvm參數(shù)指定
-javaagent:E:\IdeaProjects\javaagent\target\javaagent-1.0-SNAPSHOT.jar執(zhí)行,觀察我們引入的這個jar包中的premain方法是否優(yōu)先于這個測試類的main方法執(zhí)行
OK ,這個就是Java Agent的 簡單小栗子, 更強大的功能繼續(xù)開篇
javaagent 流程示意圖
進階Demo
public class AgentMain {public static void premain(String args, Instrumentation instrumentation)throws Exception, ClassNotFoundException {// 實例化對象UserService userService = new UserService();// 類比ClassLoaderClassPool classPool = new ClassPool();// 追加系統(tǒng)ClassLoaderclassPool.appendSystemPath();// 獲取一個類CtClass ctClass = classPool.get("com.artisan.agent.UserService");// 獲取方法CtMethod sayHello = ctClass.getDeclaredMethod("sayHello");// 在方法執(zhí)行之后插入下面這行語句sayHello.insertAfter("System.out.println(\"I am fine\");");// 重新定義一個類instrumentation.redefineClasses(new ClassDefinition(UserService.class,ctClass.toBytecode()));// 調(diào)用服務(wù) 這里的userservice 已經(jīng)是被重新定義的 對象了userService.sayHello();}總結(jié)
- 1.instrumentation addTransformer 類裝載攔截
- 2.只能攔截未裝載過的類
- 3.instrumentation#retransformClasses方法 重新裝載類 ,必須開啟相關(guān)參數(shù)
- 4.instrumentation.redefineClasses 重新定義一個類 ,不能添加新方法 ,必須開啟相關(guān)參數(shù)
開啟參數(shù)
agent 依懶包逗號分割 Boot-Class-Path: javassist-3.18.1-GA.jar 是否允許重定義 Can-Redefine-Classes: true 允許重載 Can-Retransform-Classes:trueJavassist 引入
既然是搞字節(jié)碼,有沒有類庫 ?
其實上面的栗子 其實已經(jīng)使用了Javassist 類庫了~
Javassist是一個開源的分析、編輯和創(chuàng)建Java字節(jié)碼的類庫。
關(guān)于java字節(jié)碼的處理, 目前有很多開源工具可用,比如asm,bcel, 不過這些都需要直接跟虛擬機指令打交道,實在是太難。。。。。
如果不想了解虛擬機指令,可以采用javassist。
javassist是jboss的一個子項目,優(yōu)點簡單 快速 ,直接使用java編碼的形式,而不需要了解虛擬機指令,就能動態(tài)改變類的結(jié)構(gòu),或者動態(tài)生成類。
《新程序員》:云原生和全面數(shù)字化實踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的APM - Hello Javaagent的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JVM - Class常量池 || 运行
- 下一篇: java美元兑换,(Java实现) 美元