從今天開(kāi)始分幾節(jié)介紹Java中最重要的class文件。
包括class文件的結(jié)構(gòu)、class是如何進(jìn)入到虛擬機(jī)中的(類(lèi)裝載)、class的消亡(垃圾收集)
Class 的結(jié)構(gòu)
Class 文件由 java 代碼編譯而來(lái),每個(gè)類(lèi)都會(huì)生成一個(gè) .class 文件。 Java class 文件中包含了 java 虛擬機(jī)所需知道的、關(guān)于類(lèi)或接口的所有信息。這些信息用表格的形式來(lái)說(shuō)明,我們可以得到 classfile 表:如圖 1
圖 1 classfile 表的格式
其中類(lèi)型或者為表名,或者如表 1 所示的“基本類(lèi)型”。所有存儲(chǔ)在類(lèi)型 u2 、 u4 和 u8 中的值,在 class 文件中以高位在前的形式出現(xiàn)。
U1 |
1 個(gè)字節(jié),無(wú)符號(hào)整形 |
U2 |
1 個(gè)字節(jié),無(wú)符號(hào)整形 |
U3 |
1 個(gè)字節(jié),無(wú)符號(hào)整形 |
U4 |
1 個(gè)字節(jié),無(wú)符號(hào)整形 |
表 1 class 文件“基本類(lèi)型”
Classfile 表中各項(xiàng)簡(jiǎn)介如下:
1) Magic( 魔數(shù) )
每個(gè) java class 文件的前 4 個(gè)字節(jié)被稱(chēng)為 magic number : 0xCAFEBABE 。魔數(shù)的作用在于,可以輕松的分辨出 java class 文件和非 java class 文件。
Class 文件的下面 4 個(gè)字節(jié)包含了主次版本號(hào)。隨著 java 技術(shù)的發(fā)展, java class 文件格式可能會(huì)加入新特性。 Class 文件格式一旦發(fā)生變化,版本號(hào)也會(huì)隨之變化。如果 class 文件的版本號(hào)超出了 java 虛擬機(jī)所能處理的有效范圍, java 虛擬機(jī)將不會(huì)處理該文件。
之后的是常量池。其中包含了與文件中類(lèi)和接口相關(guān)的常量。常量池中存儲(chǔ)了諸如文字字符串、 final 變量值、類(lèi)名和方法名的常量。 Java 虛擬機(jī)把常量池組織為入口列表的形式。在實(shí)際列表 constant_pool 之前,是入口在列表中的計(jì)數(shù) constant_pool_count 。
常量池中的許多入口都指向其他的常量池入口,而且 class 文件中緊隨著常量池的許多條目也會(huì)指向常量池中的入口。在整個(gè) class 文件中,指示常量池入口在常量池列表中位置的整數(shù)索引都指向這些常量池入口。列表中的一項(xiàng)索引值為 1 ,第二項(xiàng)索引值為 2 ,以此類(lèi)推。
例: act.class 的常量池。
“ { }V ”表示一個(gè)返回類(lèi)型為 void 的方法。
訪(fǎng)問(wèn)標(biāo)志。這個(gè)字段表示的意思指明了文件中定義的是類(lèi)還是接口;還定義了在類(lèi)或接口的聲明中,使用了哪種修飾符:是抽象的還是公共的,或者是 final 。類(lèi)的類(lèi)型可以為 final ,而 final 類(lèi)不可能是抽象的,同時(shí)接口也不能為 final 類(lèi)型。
這個(gè)類(lèi)的名字和超類(lèi)名字。特殊的,對(duì)于 object 類(lèi), super_class 為 0 ,除此以外 super_class 對(duì)于所有的類(lèi)均有效。對(duì)于接口,在常量池入口 super_class 位置的項(xiàng)為 java.lang.object
。
緊接著 super_class 的是 Interfaces_count 。此項(xiàng)的含義為:在文件中由該類(lèi)直接實(shí)現(xiàn)或者由該接口所擴(kuò)展的父接口的數(shù)量。在這個(gè)技術(shù)的后面,是名為 interfaces 的數(shù)組,它包含了對(duì)每個(gè)由由該類(lèi)直接實(shí)現(xiàn)或者由該接口所擴(kuò)展的父接口的常量池索引。