天天看點

ASM7 使用指南------第1章引言(如有侵權請聯系作者删除)1.1 動機

(如有侵權請聯系作者删除)

1.1 動機

        程式分析、程式生成和程式轉換都是非常有用的技術,可在許多應用環境下使用:

         □ 程式分析,既可能隻是簡單的文法分析(syntaxic parsing),也可能是完整的語義分析

(sematic analysis),可用于查找應用程式中的潛在 bug、檢測未被用到的代碼、對代碼

實施逆向工程,等等。

         □ 程式生成,在編譯器中使用。這些編譯器不僅包括傳統編譯器,還包括用于分布式程式

設計的 stub 編譯器或 skeleton 編譯器,以及 JIT(即時)編譯器,等等。

         □ 程式轉換,用于優化或混淆(obfuscate)程式、向應用程式中插入調試或性能監視代

碼,用于面向方面的程式設計,等等。

        所有這些技術都可針對任意程式設計語言使用,但對于不同語言,其使用的難易程度可能會有所不同。對于 Java 語言,它們可用于 Java 源代碼或編譯後的 Java 類。在使用經過編譯的類時,其好處之一顯然就是不需要源代碼。是以,程式轉換可用于任何應用程式,既包括保密的源代碼,也包含商業應用程式。使用已編譯類的另一個好處是,有可能在運作時,在馬上就要将類加載到Java 虛拟機之前,對類進行分析、生成或轉換(在運作時生成和編譯源代碼也可以,但其速度很慢,而且需要一個完整的 Java 編譯器)。其好處是,諸如 stub 編譯器或方面編織器等工具對使用者變為透明。

        由于程式分析、生成和轉換技術的用途衆多,是以人們針對許多語言實作了許多用于分析、生成和轉換程式的工具,這些語言中就包括 Java 在内。ASM 就是為 Java 語言設計的工具之一,用于進行運作時(也是脫機的)類生成與轉換。于是,人們設計了 ASM①庫,用于處理經過編譯的 Java 類。這個庫的設計使其盡可能保持快速和小型化。對于那些在運作時使用 ASM 進行動态類生成或轉換的應用程式來說,盡可能提高庫的運作速度是非常重要的,這樣可以保證這些應用程式的速度不緻下降過多。而保持 ASM 庫的小型化也非常重要,一方面是為了在記憶體有限的環境中使用,另一方面,也為了避免使那些使用 ASM 的小型應用程式或庫增大過多

        ASM 并不是惟一可生成和轉換已編譯 Java 類的工具,但它是最新、最高效的工具之一,可從 http://asm.objectweb.org 下載下傳。其主要優點如下:

  •  有一個簡單的子產品 API,設計完善、使用友善。
  • 文檔齊全,擁有一個相關的 Eclipse 插件。
  • 支援最新的 Java 版本——Java 8。 小而快、非常可靠。
  • 擁有龐大的使用者社群,可以為新使用者ᨀ供支援。
  • 源許可開放,幾乎允許任意使用。

1.2 概述

1.2.1 範圍

        ASM 庫的目的是生成、轉換和分析以位元組數組表示的已編譯 Java 類(它們在磁盤中的存儲和在 Java 虛拟機中的加載都采用這種位元組數組形式)。為此,ASM 提供了一些工具,使用高于位元組級别的概念來讀寫和轉換這種位元組數組,這些概念包括數值常數、字元串、Java 辨別符、Java類型、Java 類結構元素,等等。注意,ASM 庫的範圍嚴格限制于類的讀、寫、轉換和分析。具體來說,類的加載過程就超出了它的範圍之外。

1.2.2 模型

        ASM 庫提供了兩個用于生成和轉換已編譯類的 API,一個是核心 API,以基于事件的形式來表示類,另一個是樹 API,以基于對象的形式來表示類。

        在采用基于事件的模型時,類是用一系列事件來表示的,每個事件表示類的一個元素,比如它的一個标頭、一個字段、一個方法聲明、一條指令,等等。基于事件的 API 定義了一組可能事件,以及這些事件必須遵循的發生順序,還提供了一個類分析器,為每個被分析元素生成一個事件,還提供一個類寫入器,由這些事件的序列生成經過編譯的類。

        而在采用基于對象的模型時,類用一個對象樹表示,每個對象表示類的一部分,比如類本身、一個字段、一個方法、一條指令,等等,每個對象都有一些引用,指向表示其組成部分的對象。基于對象的 API提供了一種方法,可以将表示一個類的事件序列轉換為表示同一個類的對象樹,也可以反過來,将對象樹表示為等價的事件序列。換言之,基于對象的 API 建構在基于事件的API 之上。

        這兩個 API 可以與“用于 XML 的簡單 API”(Simple API for XML,SAX)和用于 XML 文檔的“文檔對象模型(Document Object Model,DOM)API”相比較:基于事件的 API 類似于SAX,而基于對象的 API 類似于 DOM。基于對象的 API 建構在基于事件的 API 之上,類似于DOM 可在 SAX 的上層提供。

        ASM 之是以要提供兩個 API,是因為沒有哪種 API 是最佳的。實際上,每個 API 都有自己的優缺點:

        □ 基于事件的 API 要快于基于對象的 API,所需要的記憶體也較少,因為它不需要在記憶體中

建立和存儲用于表示類的對象樹(SAX 與 DOM 之間也有同樣的差異)。 

        □ 但在使用基于事件的 API 時,類轉換的實作可能要更難一些,因為在任意給定時刻,

類中隻有一個元素可供使用(也就是與目前事件對應的元素),而在使用基于對象的 API

時,可以在記憶體中獲得整個類。

1.2.3 體系結構

        ASM 應用程式擁有一個很強壯的體系結構方面(aspect)。事實上,對于基于事件的 API,其組織結構是圍繞事件生成器(類分析器)、事件使用器(類寫入器)和各種預定義的事件篩選器進行的,在這一結構中可以添加使用者定義的生成器、使用器和篩選器。是以,這一 API 的使用分為兩個步驟:

  • 将事件生成器、篩選器和使用器元件組裝為可能很複雜的體系結構,
  • 然後啟動事件生成器,以執行生成或轉換過程。

        基于對象的 API 也有一個體系結構方面:實際上,用于操作類樹的類生成器或轉換器元件

是可以組成形成的,它們之間的連結代表着轉換的順序。

        盡管典型 ASM 應用程式中的大多數元件體系結構都非常簡單,但還是可以想象一下類似于

如下所示的複雜體系結構,其中的箭頭表示在類分析器、寫入器或轉換器之間進行的基于事件或基于對象的通信,在整個鍊中的任何位置,都可能會在基于事件與基于對象的表示之間進行轉換:

ASM7 使用指南------第1章引言(如有侵權請聯系作者删除)1.1 動機

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。

印刷約定

斜體用于強調句子中的元素。(譯者注:中文中一般改為加粗顯示)

定寬字型用于表示代碼段。

粗體定寬字型用于強調代碼元素。

斜體定寬字型用于表示标記和代碼中的變量部分。