這篇文章聊下位元組碼和相關的應用。
1、機器碼和位元組碼
機器碼(machine code),學名機器語言指令,有時也被稱為原生碼(Native Code),是電腦的CPU可直接解讀的資料。
通常意義上來了解的話,機器碼就是計算機可以直接執行,并且執行速度最快的代碼。
用機器語言編寫程式,程式設計人員要首先熟記所用計算機的全部指令代碼和代碼的涵義。手程式設計式時,程式員得自己處理每條指令和每一資料的存儲配置設定和輸入輸出,還得記住程式設計過程中每步所使用的工作單元處在何種狀态。這是一件十分繁瑣的工作,編寫程式花費的時間往往是實際運作時間的幾十倍或幾百倍。而且,編出的程式全是些0和1的指令代碼,直覺性差,還容易出錯。
位元組碼(Bytecode)是一種包含執行程式、由一序列 op 代碼/資料對 組成的二進制檔案。位元組碼是一種中間碼,它比機器碼更抽象,需要直譯器轉譯後才能成為機器碼的中間代碼。
通常情況下它是已經經過編譯,但與特定機器碼無關。位元組碼通常不像源碼一樣可以讓人閱讀,而是編碼後的數值常量、引用、指令等構成的序列。
位元組碼主要為了實作特定軟體運作和軟體環境、與硬體環境無關。位元組碼的實作方式是通過編譯器和虛拟機器。編譯器将源碼編譯成位元組碼,特定平台上的虛拟機器将位元組碼轉譯為可以直接執行的指令。
位元組碼的典型應用為Java bytecode。位元組碼在運作時通過JVM(JAVA虛拟機)做一次轉換生成機器指令,是以能夠更好的跨平台運作。
2、位元組碼增強技術
Java位元組碼增強指的是在Java位元組碼生成之後,對其進行修改,增強其功能,這種方式相當于對應用程式的二進制檔案進行修改。Java位元組碼增強主要是為了減少備援代碼,提高性能等。
實作位元組碼增強的主要步驟為:
(1)修改位元組碼
在記憶體中擷取到原來的位元組碼,然後通過一些工具(如 ASM,Javaasist)來修改它的byte[]數組,得到一個新的byte數組。
(2)使修改後的位元組碼生效
有兩種方法:
- 自定義ClassLoader來加載修改後的位元組碼;
- 替換掉原來的位元組碼:在JVM加載使用者的Class時,攔截,傳回修改後的位元組碼;或者在運作時,使用Instrumentation.redefineClasses方法來替換掉原來的位元組碼;
3、位元組碼增強有哪些實作
位元組碼增強技術有以下這些:
- 動态代理
- CGLIB
- Javassist
- asm
以 ASM 為例, 使用它可以動态修改類、方法,甚至可以重新定義類,連 CGLib 底層都是用 ASM 實作的。
4、Btrace原理和應用
BTrace是SUN Kenai雲計算開發平台下的一個開源項目,旨在為java提供安全可靠的動态跟蹤分析工具。
那麼,BTrace這麼神奇的功能是如何實作的呢?既然這是個開源的代碼,那麼直接從代碼找原理。BTrace代碼開源在https://github.com/btraceio/btrace。
BTrace是基于動态位元組碼修改技術(Hotswap)來實作運作時java程式的跟蹤和替換。大體的原理可以用下面的公式描述:
Client(Java compile api + attach api) + Agent(腳本解析引擎 + ASM + JDK6 Instumentation) + Socket
BTrace工作時序圖如下:

BTrace就是使用ASM修改目前類,附加調試資訊,得到新的類,一般情況下,Class檔案是通過javac編譯器産生的,然後通過類加載器加載到虛拟機内,再通過執行引擎去執行。現在可以通過ASM的API直接生成符合Java虛拟機規範的Class位元組流,這樣,ASM做的事情一定程度上正是javac解釋器做的工作。
5、總結
位元組碼增強技術可以動态地對運作中的程式做修改,也可以跟蹤JVM運作中程式的狀态。此外,我們平時使用的動态代理、AOP也與位元組碼增強密切相關,它們實質上還是利用各種手段生成符合規範的位元組碼檔案。
掌握位元組碼增強後可以高效地定位并快速修複一些棘手的問題(如線上性能問題、方法出現不可控的出入參需要緊急加日志等問題),也可以在開發中減少備援代碼,大大提高開發效率。
作者:邴越
掃碼關注公衆号:架構進化論,獲得第一手的技術資訊和原創文章
如果文章對您有幫助,可以點選文章右下角【推薦】一下,您的鼓勵是作者堅持原創和持續寫作的最大動力!