所謂 Java 類文件,就是通常用 javac 編譯器產(chǎn)生的 .class 文件。這些文件具有嚴(yán)格定義的格式。為了更好的理解 ASM,首先對(duì) Java 類文件格式作一點(diǎn)簡(jiǎn)單的介紹。Java 源文件經(jīng)過(guò) javac 編譯器編譯之后,將會(huì)生成對(duì)應(yīng)的二進(jìn)制文件(如下圖所示)。每個(gè)合法的 Java 類文件都具備精確的定義,而正是這種精確的定義,才使得 Java 虛擬機(jī)得以正確讀取和解釋所有的 Java 類文件。
Java 類文件是 8 位字節(jié)的二進(jìn)制流。數(shù)據(jù)項(xiàng)按順序存儲(chǔ)在 class 文件中,相鄰的項(xiàng)之間沒(méi)有間隔,這使得 class 文件變得緊湊,減少存儲(chǔ)空間。在 Java 類文件中包含了許多大小不同的項(xiàng),由于每一項(xiàng)的結(jié)構(gòu)都有嚴(yán)格規(guī)定,這使得 class 文件能夠從頭到尾被順利地解析。下面讓我們來(lái)看一下 Java 類文件的內(nèi)部結(jié)構(gòu),以便對(duì)此有個(gè)大致的認(rèn)識(shí)。
例如,一個(gè)最簡(jiǎn)單的 Hello World 程序:
public class HelloWorld { public static void main(String[] args) { System.out.println("Hello world"); } } |
?
經(jīng)過(guò) javac 編譯后,得到的類文件大致是:
從上圖中可以看到,一個(gè) Java 類文件大致可以歸為 10 個(gè)項(xiàng):
- Magic: 該項(xiàng)存放了一個(gè) Java 類文件的魔數(shù)(magic number)和版本信息。一個(gè) Java 類文件的前 4 個(gè)字節(jié)被稱為它的魔數(shù)。每個(gè)正確的 Java 類文件都是以 0xCAFEBABE 開(kāi)頭的,這樣保證了 Java 虛擬機(jī)能很輕松的分辨出 Java 文件和非 Java 文件。
- Version: 該項(xiàng)存放了 Java 類文件的版本信息,它對(duì)于一個(gè) Java 文件具有重要的意義。因?yàn)?Java 技術(shù)一直在發(fā)展,所以類文件的格式也處在不斷變化之中。類文件的版本信息讓虛擬機(jī)知道如何去讀取并處理該類文件。
- Constant Pool: 該項(xiàng)存放了類中各種文字字符串、類名、方法名和接口名稱、final 變量以及對(duì)外部類的引用信息等常量。虛擬機(jī)必須為每一個(gè)被裝載的類維護(hù)一個(gè)常量池,常量池中存儲(chǔ)了相應(yīng)類型所用到的所有類型、字段和方法的符號(hào)引用,因此 它在 Java 的動(dòng)態(tài)鏈接中起到了核心的作用。常量池的大小平均占到了整個(gè)類大小的 60% 左右。
- Access_flag: 該項(xiàng)指明了該文件中定義的是類還是接口(一個(gè) class 文件中只能有一個(gè)類或接口),同時(shí)還指名了類或接口的訪問(wèn)標(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)對(duì)類或接口中聲明的字段進(jìn)行了細(xì)致的描述。需要注意的是,fields 列表中僅列出了本類或接口中的字段,并不包括從超類和父接口繼承而來(lái)的字段。
- Methods: 該項(xiàng)對(duì)類或接口中聲明的方法進(jìn)行了細(xì)致的描述。例如方法的名稱、參數(shù)和返回值類型等。需要注意的 是,methods 列表里僅存放了本類或本接口中的方法,并不包括從超類和父接口繼承而來(lái)的方法。使用 ASM 進(jìn)行 AOP 編程,通常是通過(guò)調(diào)整 Method 中的指令來(lái)實(shí)現(xiàn)的。
- Class attributes: 該項(xiàng)存放了在該文件中類或接口所定義的屬性的基本信息。
事實(shí)上,使用 ASM 動(dòng)態(tài)生成類,不需要像早年的 class hacker 一樣,熟知 class 文件的每一段,以及它們的功能、長(zhǎng)度、偏移量以及編碼方式。ASM 會(huì)給我們照顧好這一切的,我們只要告訴 ASM 要改動(dòng)什么就可以了 —— 當(dāng)然,我們首先得知道要改什么:對(duì)類文件格式了解的越多,我們就能更好地使用 ASM 這個(gè)利器。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
