Javassist 字節(jié)碼學(xué)習(xí) HelloWorld,看到這樣的代碼就覺得自己會了
一、前言
在字節(jié)碼編程方面有三個比較常見的框架;ASM、byte-buddy、Javassist,他們都可以對這字節(jié)碼進行操作,只是操作方式和控制粒度不同。
其中 ASM 更偏向于底層,需要了解 JVM 虛擬機中指定規(guī)范以及對局部變量以及操作數(shù)棧的知識。雖然在編寫起來比較麻煩,但是它也是性能最好功能最強的字節(jié)碼操作框架。常見的會用在 CGLIB 動態(tài)代理類中,以及一些非入侵的探針監(jiān)控場景中。
另外兩個框架都是有強大的 API,操作使用上更加容易控制。雖然對對比上會比 ASM 性能差一些,但不是說性能完全不好。同樣在一些監(jiān)控場景中也用的非常多。如果你細心可以在你的工程 jar 包搜索一下。
在這之前我已經(jīng)編寫了 Javaagent全鏈路監(jiān)控 和 ASM 的部分文章,雖然這部分技術(shù)內(nèi)容在 CRUD 開發(fā)中并不常用,但隨著自動化測試、非入侵監(jiān)控的大量使用,還是蠻多人需要這樣的技能學(xué)習(xí)的。同時我也是這樣一個技能的學(xué)習(xí)者,為此后面會陸續(xù)編寫和完善關(guān)于 字節(jié)碼編程 這個專欄。也希望這個專欄在提升自己技術(shù)棧的同時也幫助他人成長。
那么,小傅哥計劃從 Javassist 到 ASM 陸續(xù)完成整套專欄學(xué)習(xí)的文章編寫。從簡單入門到應(yīng)用操作,一步步來完成成體系的技術(shù)知識棧學(xué)習(xí)。
好!,現(xiàn)在開始第一個Helloworld案例。相關(guān)源碼可以通過關(guān)注 公眾號:bugstack蟲洞棧 獲取
二、開發(fā)環(huán)境
- JDK 1.8.0
- javassist 3.12.1.GA <dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.12.1.GA</version>
<type>jar</type>
</dependency>
三、案例目標
不看實現(xiàn)過程的話,我們的案例目標其實很簡單,就是使用 javassist 輸出一行 Helloworld 。這話像不像產(chǎn)品說的
以上的這段代碼就是我們接下來需要使用字節(jié)碼編程技術(shù)來實現(xiàn)的內(nèi)容。
四、技術(shù)實現(xiàn)
其實輸出一個 Helloworld 還是蠻簡單的,主要是從這里面去學(xué)習(xí)一下 Javassist 的基本語法結(jié)構(gòu),也能為后續(xù)的學(xué)習(xí)有一個基礎(chǔ)的概念。
javassist Helloworld
這段代碼分為幾塊內(nèi)容來實現(xiàn)功能,分別包括;
- 創(chuàng)建 ClassPool,它是一個基于HashMap實現(xiàn)的 CtClass 對象容器。
- 使用 CtClass,創(chuàng)建我們的類信息,也就是類的路徑和名稱。
- 接下來就是給類添加方法。包括;方法的屬性、類型、名稱、入?yún)?、出參和方法體的內(nèi)容。
- 在方法創(chuàng)建好后還需要創(chuàng)建一個空的構(gòu)造函數(shù),每一個類都會在編譯后生成這樣一個構(gòu)造函數(shù)。
- 當方法創(chuàng)建完成后,我們使用 ctClass.writeFile() 進行輸出方法的內(nèi)容信息。也就可以看到通過我們使用 Javassist 生成類的樣子。
- 最后就是我們的反射調(diào)用 main 方法,測試輸出結(jié)果。
五、測試結(jié)果
當我們執(zhí)行測試的時候會輸出類信息到工程文件夾下,同時會輸出我們的測試結(jié)果;
1. 使用Javassist生成的類
使用Javassist生成的類,在工程文件夾下
2. 輸出的測試結(jié)果
六、總結(jié)
- 關(guān)于 Javassist 的使用在完整的且強大的 API 下,確實還是蠻容易使用的。并且代碼的使用上并不是很難理解。