1. 程式人生 > >從底層入手,解析位元組碼增強和Btrace應用

從底層入手,解析位元組碼增強和Btrace應用

這篇文章聊下位元組碼和相關的應用。

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也與位元組碼增強密切相關,它們實質上還是利用各種手段生成符合規範的位元組碼檔案。

掌握位元組碼增強後可以高效地定位並快速修復一些棘手的問題(如線上效能問題、方法出現不可控的出入參需要緊急加日誌等問題),也可以在開發中減少冗餘程式碼,大大提高開發效率