日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

asm 與 cglib(整理的)

 Baruch 2018-01-11

參考博客地址

http://www./user/kevin/blog/304#top

http://www./vanadies10/archive/2011/02/23/344899.html

http://llying./blog/220452

http://www.cnblogs.com/liuling/archive/2013/05/21/CGlib-AOP.html

1 asm簡介

ASM是一個(gè)Java字節(jié)碼操縱框架,它能被用來動(dòng)態(tài)生成類或者增強(qiáng)既有類的功能。ASM可以直接產(chǎn)生二進(jìn)制class文件,也可以在類被加載入Java虛擬機(jī)之前動(dòng)態(tài)改變類行為。Java class被存儲在嚴(yán)格格式定義的.class文件里,這些類文件擁有足夠的元數(shù)據(jù)來解析類中的所有元素:類名稱、方法、屬性以及 Java 字節(jié)碼(指令)。ASM從類文件中讀入信息后,能夠改變類行為,分析類信息,甚至能夠根據(jù)用戶要求生成新類。

目前許多框架如cglib、Hibernate、Spring都直接或間接地使用ASM操作字節(jié)碼,有些語言如Jython、JRuby、Groovy也是如此。而類ASM字節(jié)碼工具還有:

  1. BCEL:Byte Code Engineering Library (BCEL),這是Apache Software Foundation 的Jakarta 項(xiàng)目的一部分。BCEL是 Java classworking 最廣泛使用的一種框架,它可以讓您深入 JVM 匯編語言進(jìn)行類操作的細(xì)節(jié)。BCEL與Javassist 有不同的處理字節(jié)碼方法,BCEL在實(shí)際的JVM 指令層次上進(jìn)行操作(BCEL擁有豐富的JVM 指令級支持)而Javassist 所強(qiáng)調(diào)的源代碼級別的工作。
  2. JBET:通過JBET(Java Binary Enhancement Tool )的API可對Class文件進(jìn)行分解,重新組合,或被編輯。JBET也可以創(chuàng)建新的Class文件。JBET用一種結(jié)構(gòu)化的方式來展現(xiàn)Javabinary (.class)文件的內(nèi)容,并且可以很容易的進(jìn)行修改。
  3. Javassist:Javassist是一個(gè)開源的分析、編輯和創(chuàng)建Java字節(jié)碼的類庫。是由東京技術(shù)學(xué)院的數(shù)學(xué)和計(jì)算機(jī)科學(xué)系的 Shigeru Chiba 所創(chuàng)建的。它已加入了開放源代碼JBoss 應(yīng)用服務(wù)器項(xiàng)目,通過使用Javassist對字節(jié)碼操作為JBoss實(shí)現(xiàn)動(dòng)態(tài)AOP框架。
  4. cglib:是一個(gè)強(qiáng)大的,高性能,高質(zhì)量的Code生成類庫。它可以在運(yùn)行期擴(kuò)展Java類與實(shí)現(xiàn)Java接口,cglib封裝了asm,可以在運(yùn)行期動(dòng)態(tài)生成新的 class,Hibernate和Spring都用到過它。cglib用于AOP,jdk中的proxy必須基于接口,cglib卻沒有這個(gè)限制。

而ASM與cglib、serp和BCEL相比,ASM有以下的優(yōu)點(diǎn) :

  • ASM 具有簡單、設(shè)計(jì)良好的 API,這些 API 易于使用;
  • ASM 有非常良好的開發(fā)文檔,以及可以幫助簡化開發(fā)的 Eclipse 插件;
  • ASM 支持 Java 6(ASM3)、Java7(ASM4)、Java(ASM5);
  • ASM 很小、很快、很健壯;
  • ASM 有很大的用戶群,可以幫助新手解決開發(fā)過程中遇到的問題;
  • ASM 的開源許可可以讓你幾乎以任何方式使用它;

2 asm jar包簡介

  在ASM3.3.1中,提供了7個(gè)jar包,分別是

         asm-3.3.1.jar

         asm-commons-3.3.1.jar

   asm-tree-3.3.1.jar

         asm-analysis-3.3.1.jar

         asm-util-3.3.1.jar

         asm-xml-3.3.1.jar

 

         參看ASM的javadoc(http://asm./asm33/javadoc/user/index.html),可以看到一共有7個(gè)package,package和jar的對應(yīng)關(guān)系如下

    asm-3.3.1.jar 包含了org.objectweb.asm和org.objectweb.asm.signature兩個(gè)packages

     asm-commons-3.3.1.jar包含了org.objectweb.asm.commons這個(gè)package

     asm-tree-3.3.1.jar 包含了org.objectweb.asm.tree這個(gè)package

     asm-analysis-3.3.1.jar包含了org.objectweb.asm.tree.analysis這個(gè)package

     asm-util-3.3.1.jar包含了org.objectweb.asm.util這個(gè)package

        asm-xml-3.3.1.jar包含了org.objectweb.asm.xml這個(gè)package

        其中asm-3.3.1.jar,是包含了核心的功能,而其他的jar,都是基于這個(gè)核心的擴(kuò)展。

 

3  Java字節(jié)碼文件

所謂 Java 字節(jié)碼文件,就是通常用 javac 編譯器產(chǎn)生的 .class 文件。這些文件具有嚴(yán)格定義的格式。為了更好的理解 ASM,首先對 Java 字節(jié)碼文件格式作一點(diǎn)簡單的介紹。Java 源文件經(jīng)過 javac 編譯器編譯之后,將會生成對應(yīng)的二進(jìn)制文件(如下圖所示)。每個(gè)合法的 Java 字節(jié)碼文件都具備精確的定義,而正是這種精確的定義,才使得 Java 虛擬機(jī)得以正確讀取和解釋所有的 Java 字節(jié)碼文件。

Java 字節(jié)碼文件是 8 位字節(jié)的二進(jìn)制流。數(shù)據(jù)項(xiàng)按順序存儲在 class 文件中,相鄰的項(xiàng)之間沒有間隔,這使得 class 文件變得緊湊,減少存儲空間。在 Java 字節(jié)碼文件中包含了許多大小不同的項(xiàng),由于每一項(xiàng)的結(jié)構(gòu)都有嚴(yán)格規(guī)定,這使得 class 文件能夠從頭到尾被順利地解析。下面讓我們來看一下 Java 字節(jié)碼文件的內(nèi)部結(jié)構(gòu),以便對此有個(gè)大致的認(rèn)識。

例如,一個(gè)最簡單的 Hello World 程序:

  1. public class HelloWorld {
  2. public static void main(String[] args) {
  3. System.out.println('Hello world');
  4. }
  5. }

從上圖中可以看到,一個(gè) Java 字節(jié)碼文件大致可以歸為 10 個(gè)項(xiàng):

  • Magic:該項(xiàng)存放了一個(gè) Java 字節(jié)碼文件的魔數(shù)(magic number)和版本信息。一個(gè) Java 字節(jié)碼文件的前 4 個(gè)字節(jié)被稱為它的魔數(shù)。每個(gè)正確的 Java 字節(jié)碼文件都是以 0xCAFEBABE 開頭的,這樣保證了 Java 虛擬機(jī)能很輕松的分辨出 Java 文件和非 Java 文件。
  • Version:該項(xiàng)存放了 Java 字節(jié)碼文件的版本信息,它對于一個(gè) Java 文件具有重要的意義。因?yàn)?Java 技術(shù)一直在發(fā)展,所以字節(jié)碼文件的格式也處在不斷變化之中。字節(jié)碼文件的版本信息讓虛擬機(jī)知道如何去讀取并處理該字節(jié)碼文件。
  • Constant Pool:該項(xiàng)存放了類中各種文字字符串、類名、方法名和接口名稱、final 變量以及對外部類的引用信息等常量。虛擬機(jī)必須為每一個(gè)被裝載的類維護(hù)一個(gè)常量池,常量池中存儲了相應(yīng)類型所用到的所有類型、字段和方法的符號引用,因此它在 Java 的動(dòng)態(tài)鏈接中起到了核心的作用。常量池的大小平均占到了整個(gè)類大小的 60% 左右。
  • Access_flag:該項(xiàng)指明了該文件中定義的是類還是接口(一個(gè) class 文件中只能有一個(gè)類或接口),同時(shí)還指名了類或接口的訪問標(biāo)志,如 public,private, abstract 等信息。
  • This Class:指向表示該類全限定名稱的字符串常量的指針。
  • Super Class:指向表示父類全限定名稱的字符串常量的指針。
  • Interfaces:一個(gè)指針數(shù)組,存放了該類或父類實(shí)現(xiàn)的所有接口名稱的字符串常量的指針。以上三項(xiàng)所指向的常量,特別是前兩項(xiàng),在我們用 ASM 從已有類派生新類時(shí)一般需要修改:將類名稱改為子類名稱;將父類改為派生前的類名稱;如果有必要,增加新的實(shí)現(xiàn)接口。
  • Fields:該項(xiàng)對類或接口中聲明的字段進(jìn)行了細(xì)致的描述。需要注意的是,fields 列表中僅列出了本類或接口中的字段,并不包括從超類和父接口繼承而來的字段。
  • Methods:該項(xiàng)對類或接口中聲明的方法進(jìn)行了細(xì)致的描述。例如方法的名稱、參數(shù)和返回值類型等。需要注意的是,methods 列表里僅存放了本類或本接口中的方法,并不包括從超類和父接口繼承而來的方法。使用 ASM 進(jìn)行 AOP 編程,通常是通過調(diào)整 Method 中的指令來實(shí)現(xiàn)的。
  • Class attributes:該項(xiàng)存放了在該文件中類或接口所定義的屬性的基本信息。

事實(shí)上,使用 ASM 動(dòng)態(tài)生成類,不需要像早年的 class hacker 一樣,熟知 class 文件的每一段,以及它們的功能、長度、偏移量以及編碼方式。ASM 會給我們照顧好這一切的,我們只要告訴 ASM 要改動(dòng)什么就可以了 —— 當(dāng)然,我們首先得知道要改什么:對字節(jié)碼文件格式了解的越多,我們就能更好地使用 ASM 這個(gè)利器。

ASM編程模型

ASM 提供了兩種編程模型:

  • Core API,提供了基于事件形式的編程模型。該模型不需要一次性將整個(gè)類的結(jié)構(gòu)讀取到內(nèi)存中,因此這種方式更快,需要更少的內(nèi)存。但這種編程方式難度較大。
  • Tree API,提供了基于樹形的編程模型。該模型需要一次性將一個(gè)類的完整結(jié)構(gòu)全部讀取到內(nèi)存當(dāng)中,所以這種方法需要更多的內(nèi)存。這種編程方式較簡單。

Core API 中操縱字節(jié)碼的功能基于 ClassVisitor 接口。這個(gè)接口中的每個(gè)方法對應(yīng)了 class 文件中的每一項(xiàng)。Class 文件中的簡單項(xiàng)的訪問使用一個(gè)單獨(dú)的方法,方法參數(shù)描述了這個(gè)項(xiàng)的內(nèi)容。而那些具有任意長度和復(fù)雜度的項(xiàng),使用另外一類方法,這類方法會返回一個(gè)輔助的 Visitor 接口,通過這些輔助接口的對象來完成具體內(nèi)容的訪問。例如 visitField 方法和 visitMethod 方法,分別返回 FieldVisitor 和 MethodVisitor 接口的對象。

ASM 提供了三個(gè)基于 ClassVisitor 接口的類來實(shí)現(xiàn) class 文件的生成和轉(zhuǎn)換:

  • ClassReader:ClassReader 解析一個(gè)類的 class 字節(jié)碼,該類的 accept 方法接受一個(gè) ClassVisitor 的對象,在 accept 方法中,會按上文描述的順序逐個(gè)調(diào)用 ClassVisitor 對象的方法。它可以被看做事件的生產(chǎn)者。
  • ClassAdapter:ClassAdapter 是 ClassVisitor 的實(shí)現(xiàn)類。它的構(gòu)造方法中需要一個(gè) ClassVisitor 對象,并保存為字段 protected ClassVisitor cv。在它的實(shí)現(xiàn)中,每個(gè)方法都是原封不動(dòng)的直接調(diào)用 cv 的對應(yīng)方法,并傳遞同樣的參數(shù)??梢酝ㄟ^繼承 ClassAdapter 并修改其中的部分方法達(dá)到過濾的作用。它可以看做是事件的過濾器。
  • ClassWriter:ClassWriter 也是 ClassVisitor 的實(shí)現(xiàn)類。ClassWriter 可以用來以二進(jìn)制的方式創(chuàng)建一個(gè)類的字節(jié)碼。對于 ClassWriter 的每個(gè)方法的調(diào)用會創(chuàng)建類的相應(yīng)部分。例如:調(diào)用 visit 方法就是創(chuàng)建一個(gè)類的聲明部分,每調(diào)用一次 visitMethod 方法就會在這個(gè)類中創(chuàng)建一個(gè)新的方法。在調(diào)用 visitEnd 方法后即表明該類的創(chuàng)建已經(jīng)完成。它最終生成一個(gè)字節(jié)數(shù)組,這個(gè)字節(jié)數(shù)組中包含了一個(gè)類的 class 文件的完整字節(jié)碼內(nèi)容 。可以通過 toByteArray 方法獲取生成的字節(jié)數(shù)組。ClassWriter 可以看做事件的消費(fèi)者

5 ASMifer 工具

  直接編碼ASM其實(shí)對于新手來說是很困難的事,但幸運(yùn)的是ASM給我們提供了ASMifer工具。一般我們會使用ASM的ASMifer工具生成ASM結(jié)構(gòu)來對比,使用命令:

  1. java org.objectweb.asm.util.ASMifier net.oseye.demoasm.HelloWorld

6 例子:參考地址

  http://www./vanadies10/archive/2011/02/23/344899.html

  http://llying./blog/220452

  http://www.cnblogs.com/liuling/archive/2013/05/21/CGlib-AOP.html

  代碼 : 

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多