javase 面試之Java Agent

引言

以前在做後臺服務開發的時候,SpringBoot每次改動代碼都需要手動重啓才能生效,感覺賊麻煩,後來使用Spring提供的一款熱部署插件,它只是部分重啓,相當於重新加載了我們自己寫的代碼,效率提高很多。後來遇到了Jrebel,它只重新加載我們修改的那個類,比Springboot熱部署插件重啓速度更快,連改mybatis的xml文件都能熱部署,太方便了有不有!(順便安利一下同一家公司的另一個軟件XRebel,實時監控服務請求)後來又接觸了BTrace,它可以線上調試代碼而不需要重啓項目,也是很吊的一個東西。通過了解,上面所說的幾個東西都是通過Java Agent來實現的,那麼Java Agent到底是啥,爲啥這麼吊?

簡介

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

Agent實例

Agent分爲兩種,一種是在主程序之前運行的Agent,一種是在主程序之後運行的Agent(前者的升級版,1.6以後提供),這兩種我們都會舉個🌰。

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

1、首先寫一個agent程序

代碼很簡單,只有一個premain方法,顧名思義它代表着他將在主程序的main方法之前運行,agentArgs代表傳遞過來的參數,inst則是agent技術主要使用的API,我們可以使用它來改變和重新定義類的行爲(這篇文章不會介紹,想了解的同學可以看文末的鏈接),這裏我們簡單的進行一下參數打印。

2、編寫MANIFEST.MF文件

MANIFEST.MF文件用於描述Jar包的信息,例如指定入口函數等。我們需要在該文件中加入如下配置,指定我們編寫的含有premain方法類的全路徑,然後將agent類打成Jar包。

如果你是使用Maven來構建的項目,在構建的時候加入如下代碼,否則Maven會生成自己的MANIFEST.MF覆蓋掉你的。

3、編寫我們的主程序

這裏的程序就是我們要代理的程序,我們在主程序的VM options添加上啓動參數

-javaagent: 你的路徑/test-1.0-SNAPSHOT.jar=hah

其中hah爲上文中傳入permain方法的agentArgs參數。運行我們的主程序

可以看到,我們Jar包中premain方法中的的代碼在主函數運行之前就已經成功運行了!

二、在主程序運行之後的代理程序

在主程序運行之前的agent模式有一些缺陷,例如需要在主程序運行前就指定javaagent參數,premain方法中代碼出現異常會導致主程序啓動失敗等,爲了解決這些問題,JDK1.6以後提供了在程序運行之後改變程序的能力。它的實現步驟和之前的模式類似

1、編寫agent類

我們複用上面的類,將premain方法修改爲agentmain方法,由於是在主程序運行後再執行,意味着我們可以獲取主程序運行時的信息,這裏我們打印出來主程序中加載的類名。

2、修改MANIFEST.MF文件

添加Agent-Class參數,打成Jar包

3、啓動主程序,編寫加載agent類的程序

在程序運行後加載,我們不可能在主程序中編寫加載的代碼,只能另寫程序,那麼另寫程序如何與主程序進行通信?這裏用到的機制就是attach機制,它可以將JVM A連接至JVM B,併發送指令給JVM B執行,JDK自帶常用工具如jstack,jps等就是使用該機制來實現的。這裏我們先用tomcat啓動一個程序用作主程序B,再來寫A程序代碼

我們使用VirtualMachine attach到目標進程,其中78256爲tomcat進程的PID,可以使用jps命令獲得,也可以使用VirtualMachine.list方法獲取本機上所有的Java進程,再來判斷tomcat進程,loadAgent方法第一個參數爲Jar包在本機中的路徑,第二個參數爲傳入agentmain的args參數,此處爲null,運行程序

然而什麼都沒有打印啊!是不是什麼地方寫錯了呢?仔細想想就會發現,我們是將進程attach到了tomcat進程上,agent其實是在主程序B中運行的,所以程序A中自然就不會進行打印,我們跳回tomcat程序的控制檯,查看結果。

由於是真實公司項目,項目名打碼了

可以看到,agentmain方法中的代碼已經在主程序中順利運行了,並且打印出了程序中加載的類!

總結

以上就是Java Agent的倆個簡單小栗子了,Java Agent十分強大,它能做到的不僅僅是打印幾個監控數值而已,還包括使用Transformer(推薦觀看等高級功能進行類替換,方法修改等,要使用Instrumentation的相關API則需要對字節碼等技術有較深的認識。


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章