第一章:ASM介紹
1.1 ASM動機:
程序的分析,生成,轉換技術可以應用到許多場景:
1.程序分析,從簡單的語法解析到完整的語義分析,可以應用在程序中找到潛在的bug,發現無用的代碼,工程代碼的逆向等等。
2.代碼生成應用在各種編譯器中:既包括傳統的編譯器也包括分布式編程的stub或者skeleton編譯器,即時編譯器等等。
3. 代碼轉換,可用於優化或混淆程序,向應用中插入測試或性能監控程序,面向切面編程等等。
這些技術可以用在任何編程語言,但或多或少容易依賴語言。在java 語言中,它們可以應用在源碼中也可以應用在編譯后的class文件中。用在編譯后的class文件中的好處之一是:顯然,不需要源代碼。代碼轉換可以應用到任意的應用,包括源碼封閉的應用和商業應用中。另外一個應用到編譯后的代碼是:可以在運行時期(即在類被加載到java虛擬機之前)來分析,產生,轉換類。java虛擬機用來在運行時期產生、編譯源代碼,但它比較慢並且要求有一個完整的java編譯器。好處是:對用戶來說,這類工具例如stub編譯器或者切面編織器是透明的。
由於程序分析,產生和轉換技術有如此多種用途,很多種語言包含java的分析、生成和轉換的工具已經被開發出來了。ASM就是一種專為java語言設計的在運行時期(不是離線)的類產生、轉換的工具。因此ASM庫專為編譯后的java類文件。它設計的盡可能的運行快,占用空間少。盡可能的快是為了盡可能不影響在運行期使用ASM應用的速度;盡可能的小是為了用在內存資源受到嚴格限制的環境避免因為使用ASM而造成小應用或者庫的空間膨脹。
ASM不僅僅是一個產生、轉換編譯后的java類的工具,它同時也是一種最現代最有效率的工具。可以從http://asm.objectweb.org下載到ASM. ASM的主要特點有以下幾點:
1. 它有一個簡單易用的、完美設計的、模塊化的API.
2. 它文檔完善並有一個Eclipse關聯的插件。
3. 它提供對java 最新版本java 7的支持。
4. 體積小,速度快,健壯性好。
5. 對新用戶提供龐大的社區支持。
6. 開源,允許你任意使用。
1.2 ASM 概述:
1. 域
ASM庫的目標是為了產生、轉換、分析編譯后的JAVA 類(表現為字節數組,因為它們存儲在磁盤上然后被加載到java 虛擬機中)。正因為有此目標,ASM提供了對這些字節數組讀寫和轉換的工具,這些工具使用比字節更高級別的抽象如數字常量,字符串,java標識符,java 類型,java類結構元素等進行讀寫和轉換。注意:ASM庫的域被嚴格限定在對類的讀寫,轉換和分析。特別是類的加載時超過這個域的。
2. 模型
ASM庫提供兩種類型的API來產生,轉換編譯后的類:核心API提供基於事件的類的展現;樹API提供了一個基於對象的展現。
基於事件的模型中,一個類表現為一個事件序列,每個時間代表了類的一個元素,例如header、field、method聲明、一條指令等。基於事件的API定義了的一組可能事件和必須發生的順序,並提供了一個類解析器:它根據它解析的每一個元素產生一個事件;一個寫入器:從事件序列中產生編譯后的類。
基於對象的模型中,一個類表現為一個對象樹,每個對象代碼了類的一部分,例如:類本身,一個field,一個方法,一條指令等。每個對象具有代表其組成的對象引用。基於對象的API提供了將代表一個類的事件序列轉換成代表同一個類的對象樹的方法,反之亦然,將一個對象樹轉換為等同的事件序列。換句話說,基於對象的API 建立在基於事件的API之上。這個兩個API的對比可以形容為:SAX(xml簡單api)和DOM(文檔對象模型),其中基於事件的API類似於SAX,基於對象的API類似於DOM。基於對象的API建立在基於事件的API之上,正如DOM建立在SAX上一樣。
ASM提供了這兩種API,因為沒有一種API 能比另外一種API更好。事實上,每個API都有自己的優缺點:
1、基於事件的API比基於對象的API的速度更快,需要的空間更少。因為不需要再內存中創建和存儲一個代表類的對象樹(同樣的情況也存在於SAX和DOM之間)。
2、 基於事件的API更難於實現類的轉換,因為在任意時間只能訪問到類的一個元素(對應當前時間的元素),而基於對象的API都可以在內存中訪問到。
注意:兩種API只能在一個事件管理一個類,並且各自獨立。類的繼承信息沒有保存,若一個類的轉換影響到別的類,必須由用戶去修改那些類。
3. 架構:
ASM 應用有很強的架構視圖。事實上,基於事件的API圍繞事件生成者(類解析器)、事件消費者(類寫入器)和各種預定義的過濾器進行組織,用戶定義的生產者、消費者和各種過濾器可以很容易添加上去。因而使用此API需要兩步:
1、將事件的生產者、過濾器、消費者組件匯編成復雜的架構。
2、然后運行事件生產者來運行產生或者轉換進程。
基於對象的API同樣有一個架構視圖:由操作對象樹的類產生器和轉換器組件構成,兩者的連接表示轉換的順序。
盡管大部分組件架構特別是ASM應用是非常簡單的,但也能夠聯想到復雜的架構,如下:
箭頭代表類解析器、寫入器、轉換器之間基於事件或者基於對象的連接,在鏈型結構中到處存在基於事件或者對象的轉換。
1.3 組織結構:
ASM庫有幾個不同的包組成,它們被放入到不同的jar文件中:
包org.objectweb.asm 和org.objectweb.asm.signature定義了基於事件的API,並且提供了類解析器和寫入器組件,它們被打入到asm.jar文件中。
包org.objectweb.asm.util,被打入到asm-util.jar文件中,提供了許多基於核心API的工具,這些工具可以用在ASM應用的開發和調試當中。
包org.objectweb.asm.commons提供了一些有用的預定義類轉換器,大部分基於核心API。它被打包到asm-commons.jar。
包org.objectweb.asm.tree,打包到asm-tree.jar文件中,定義了基於對象的API,提供了基於事件和基於對象的表現形式的轉換工具。
包org.objectweb.asm.tree.analysis提供了基於樹API的一個類分析框架和一些類分析器,打包到asm-analysis.jar文件。
該文檔包含兩個部分,第一部分介紹了核心API,例如:asm,asm-util和asm-commons文件。第二部分介紹了樹API,例如:asm-tree和asm-analysis文件。每部分至少有一章介紹關聯類的API,一章關聯方法的API,一章關聯注解、通用類型等的API。每章包含編程接口和相關工具及預定義組件。所有的實例源碼均可在ASM官方網站下載。
這種組織形式可以更容易地逐步引入類文件的各種特征,但有時需要在部分章節中擴展單個ASM類的表現形式。因此,建議按照文檔的順序安排來讀取。如果僅使用該手冊文檔的ASM API,請使用Javadoc
排版約定
<略>
致謝
感謝François Horn。在編纂這篇文檔期間,他的有價值的評論大大提高了該文檔的結構和可讀性。
核心API、TREE API后續中。。。。