日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java Agent

發布時間:2024/4/13 java 84 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java Agent 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在java代碼開發過程中,有些測試環境的bug,通過java? jdwp(?Java Debug Wire Protocol)進行遠程調試。jdwp定義了調試器(debugger)和被調試的 Java 虛擬機(target vm)之間的通信協議。

Target vm 中運行著我們希望要調試的程序,它與一般運行的 Java 虛擬機沒有什么區別,只是在啟動時加載了 Agent JDWP 從而具備了調試功能。而 debugger 就是我們熟知的調試器,它向運行中的 target vm 發送命令來獲取 target vm 運行時的狀態和控制 Java 程序的執行。Debugger 和 target vm 分別在各自的進程中運行,他們之間的通信協議就是 JDWP。

JDWP 與其他許多協議不同,它僅僅定義了數據傳輸的格式,但并沒有指定具體的傳輸方式。這就意味著一個 JDWP 的實現可以不需要做任何修改就正常工作在不同的傳輸方式上

Target vm 端,JDWP 模塊必須以 Agent library 的形式在 Java 虛擬機啟動時加載,并且它必須通過 Java 虛擬機提供的 JVMTI 接口實現各種 debug 的功能,所以必須使用 C/C++ 語言編寫。而 debugger 端就沒有這樣的限制,可以使用任意語言編寫,只要遵守 JDWP 規范即可。JDI(Java Debug Interface)就包含了一個 Java 的 JDWP debugger 端的實現,JDK 中調試工具 jdb 也是使用 JDI 完成其調試功能的。

JDWP的更深介紹參考:?https://www.jianshu.com/p/134bd5b913c5

JDWP使用

服務器端

服務器端需要加載jdwp,設置方式如下:

CMD java -Djava.security.egd=file:/dev/./urandom $TRACK -jar $JAVA_OPTS -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=9052 data-assets-biz.jar

需要加載jdwp agent。?

參數說明:

  • transport:指定了調試數據的傳送方式
  • dt_socket:是指用SOCKET模式
  • address: 端口或者HOST:PORT
  • server=y/n VM 是否需要作為調試服務器執行。?
  • suspend=y/n 在調試客戶端建立連接之后是否掛起。

本地端

IDEA 配置調試。

進行斷點調試時,遠程服務器會掛起。

Agent

jdwp使用的是agent技術。在JDK1.5以后,可以使用agent技術構建一個獨立于應用程序的代理程序(即為Agent),用來協助監測、運行甚至替換其他JVM上的程序。使用它可以實現虛擬機級別的AOP功能。

Agent分為兩種,一種是在主程序之前運行的Agent,一種是在主程序之后運行的Agent(前者的升級版,1.6以后提供)。

主程序

package study;public class AgentTest {public static void main(String[] args) {System.out.println("this is main process");} }

在主程序運行之前的代理程序

1、編寫agent程序

package agent;import java.lang.instrument.Instrumentation;public class TestAgent {public static void premain(String agentArgs, Instrumentation ins){System.out.println("premain start...");System.out.println(agentArgs);} }

2、配置MANIFEST.MF

<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>3.2.0</version><configuration><archive><manifest><addClasspath>true</addClasspath></manifest><manifestEntries><Premain-Class>agent.TestAgent</Premain-Class></manifestEntries></archive></configuration></plugin></plugins></build>

3、主程序加載agent程序

java -cp ./agent-test-0-1.0.jar -javaagent:./agent-test-pre-1.0.jar=x study.AgentTest

輸出:

premain start...
x
this is main process?

agent詳解

參數 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 方法。

    在主程序運行之后的代理程序

    premain 只能在類加載之前修改字節碼,類加載之后無能為力,只能通過重新創建ClassLoader 這種方式重新加載。而 agentmain 就是為了彌補這種缺點而誕生的。簡而言之,agentmain 可以在類加載之后再次加載一個類,也就是重定義,你就可以通過在重定義的時候進行修改類了,甚至不需要創建新的類加載器,JVM 已經在內部對類進行了重定義。

    但是這種方式對類的修改是由限制的,對比原來的老類,由如下要求:

    1.父類是同一個;
    2. 實現的接口數也要相同;
    3. 類訪問符必須一致;
    4. 字段數和字段名必須一致;
    5. 新增的方法必須是 private static/final 的;
    6. 可以刪除修改方法;

    可以看的出來,相比較重新創建類加載器,限制還是挺多的,最重要的字段是無法修改的。因此,使用的時候要注意。

    但是,agentmain 還有一個強大的特點,就是目標程序什么都不需要管,就能夠被代理。還記得 premain 是如何使用的嗎?需要在目標應用啟動的時候增加 -javaagent 參數。雖說沒有侵入性,但相比 agentmain 而言,還是有侵入性的,畢竟 agentmain 什么都不要。目標程序獨立運行,什么都不用管。

    ?

    1、編寫agent程序

    package agent;import java.lang.instrument.Instrumentation;public class TestAgent4 {public static void agentmain(String agentArgs , Instrumentation inst){System.out.println("load agent after main run.args=" + agentArgs);Class<?> [] classes = inst.getAllLoadedClasses();for(Class<?> c :classes){System.out.println(c.getCanonicalName());}System.out.println("agent run complete." );} }

    2、配置MANIFEST.MF

    <build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>3.2.0</version><configuration><archive><manifest><addClasspath>true</addClasspath></manifest><manifestEntries><Agent-Class>agent.TestAgent4</Agent-Class></manifestEntries></archive></configuration></plugin></plugins></build>

    3、主程序加載agent程序

    package study;public class AgentTest {public static void main(String[] args) {System.out.println("this is main process");List<VirtualMachineDescriptor> list = VirtualMachine.list();for (VirtualMachineDescriptor vmd : list) {if (vmd.displayName().endsWith("AccountMain")) {VirtualMachine virtualMachine = VirtualMachine.attach(vmd.id());virtualMachine.loadAgent("F:\\agent-test-post-1.0.jar");System.out.println("ok");virtualMachine.detach();}}} }

    需要先attach到一個VM,再加載agent。不是把agent加載到本VM。

    ?

    輸出:

    ?

    MANIFEST.MF參考:https://blog.csdn.net/demon7552003/article/details/106568285

    ?

    ?

    ?

    ?

    ?

    總結

    以上是生活随笔為你收集整理的Java Agent的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。