Class 文件中的字段表、方法表與屬性表
1. 前言
本節(jié)內(nèi)容主要是介紹 Class 文件結(jié)構(gòu)中的字段表、方法表與屬性表。從本節(jié)標(biāo)題的描述中,我們只看到了這 3 種表結(jié)構(gòu),但實(shí)際上本節(jié)會(huì)講解 6 種結(jié)構(gòu),因?yàn)槊恳环N表結(jié)構(gòu),都需要有計(jì)數(shù)器進(jìn)行計(jì)數(shù)。本節(jié)主要知識(shí)點(diǎn)如下:
- 字段表計(jì)數(shù)器和字段表的定義及意義,以及結(jié)構(gòu)示意圖,為本節(jié)重點(diǎn)內(nèi)容之一;
- 方法表計(jì)數(shù)器和方法表的定義及意義,以及結(jié)構(gòu)示意圖,為本節(jié)重點(diǎn)內(nèi)容之一;
- 屬性表計(jì)數(shù)器和屬性表的定義及意義,以及結(jié)構(gòu)示意圖,為本節(jié)次重點(diǎn)內(nèi)容,由于JVM 對(duì)屬性表沒有特別規(guī)范的限制,此處了解其定義及結(jié)構(gòu)即可。
本節(jié)所講解的內(nèi)容,是Class 文件結(jié)構(gòu)的最后部分,學(xué)習(xí)完本節(jié)課程后,會(huì)對(duì) Class 文件結(jié)構(gòu)有一個(gè)整體的認(rèn)識(shí),并且每一部分的結(jié)構(gòu)順序與課程中講解的順序完全一樣,把所有的示意圖進(jìn)行拼接,就能夠形成一個(gè)完成的 Class 文件結(jié)構(gòu)示意圖。
2. 字段表計(jì)數(shù)器和字段表
上節(jié)課程拋出了問題,接口索引集合后邊緊跟的結(jié)構(gòu)是什么?這里我們來進(jìn)行解答,后邊緊跟的是字段表計(jì)數(shù)器,字段表計(jì)數(shù)器后邊緊跟的是字段表。
定義:字段表計(jì)數(shù)器(fields_count)與字段表不可分割,這里我們對(duì)兩部分結(jié)構(gòu)一起講解。
- 字段表計(jì)數(shù)器(fields_count):記錄字段表中字段的數(shù)量,為無符號(hào)數(shù)類型。
- 字段表(fields):字段表(fields)用于描述接口或者類中聲明的變量。字段(field)包括類級(jí)變量(即靜態(tài)變量)以及實(shí)例變量(即:非靜態(tài)變量),但不包括在方法內(nèi)部聲明的局部變量。字段表為表類型結(jié)構(gòu)。
Tips:這里請(qǐng)學(xué)習(xí)者特別關(guān)注下字段表定義介紹中的最后兩句話:“字段(field)包括類級(jí)變量(即靜態(tài)變量)以及實(shí)例變量(即:非靜態(tài)變量),但不包括在方法內(nèi)部聲明的局部變量?!?簡(jiǎn)單的總結(jié)這句話的意思是字段表中存儲(chǔ)的是全局標(biāo)量,不存儲(chǔ)局部變量。
字段表計(jì)數(shù)器無符號(hào)數(shù)結(jié)構(gòu)示意圖:與其他計(jì)數(shù)器一樣,字段表計(jì)數(shù)器(fields_count)是一個(gè)無符號(hào)數(shù)結(jié)構(gòu)類型的數(shù)據(jù),u2 大小。
字段表-表結(jié)構(gòu)類型示意圖:字段表是一個(gè)表結(jié)構(gòu)的類型數(shù)據(jù),回憶下我們接觸到的第一個(gè) Class 文件的表結(jié)構(gòu)類型數(shù)據(jù)為常量池。這里我們來看下字段表的表結(jié)構(gòu)示意圖。
前文提到過,字段(field)包括類級(jí)變量(即靜態(tài)變量)以及實(shí)例變量(即:非靜態(tài)變量),上圖所示的一個(gè) field_info 就代表了一個(gè)變量。為了表示一個(gè)變量,需要知道這個(gè)變量的修飾符,如 public,還需要知道這個(gè)變量的變量名稱,因此一個(gè) field_info 中存儲(chǔ)了很多特征值,所有的特征值綜合起來就完整的描述了一個(gè)變量。
3. 方法表計(jì)數(shù)器與方法表
字段表后邊緊跟的是方法表計(jì)數(shù)器,方法表計(jì)數(shù)器后邊緊跟的是方法表。
定義:方法表計(jì)數(shù)器(methods_count)與方法表不可分割,這里我們對(duì)兩部分結(jié)構(gòu)一起講解。
- 方法表計(jì)數(shù)器(methods_count):記錄方法表中字段的數(shù)量,為無符號(hào)數(shù)類型。
- 方法表(methods):存儲(chǔ)了當(dāng)前類或者當(dāng)前接口中的 public 方法,protected 方法,default 方法,private 方法等。方法表為表結(jié)構(gòu)類型。
Tips:Class文件是通過Java文件編譯而來的,如果文件中有方法,就會(huì)將方法的信息存儲(chǔ)到方法表,并通過方法表計(jì)數(shù)器進(jìn)行方法的計(jì)數(shù)。
方法表計(jì)數(shù)器無符號(hào)數(shù)結(jié)構(gòu)示意圖:與其他計(jì)數(shù)器一樣,方法表計(jì)數(shù)器(methods_count)是一個(gè)無符號(hào)數(shù)結(jié)構(gòu)類型的數(shù)據(jù),u2 大小。
方法表-表結(jié)構(gòu)類型示意圖:方法表是一個(gè)表結(jié)構(gòu)的類型數(shù)據(jù),與前文所講解的字段表結(jié)構(gòu)一樣。
一個(gè)method_info中會(huì)存儲(chǔ)很多方法的特征值,我們通過如下示例方法進(jìn)行舉例:
public String get(String name) {
return "";
}
對(duì)于get 方法,method_info 中會(huì)存儲(chǔ)如下信息:
- 方法的修飾符 public:還記的我們上節(jié)所講述的 access_flag 嗎?access_flag 對(duì)應(yīng)表中有一個(gè) ACC_PUBLIC 就代表了 public 修飾符,他對(duì)應(yīng)的值為
0x0001
,此處的標(biāo)記也需要使用到這個(gè)表。都是通用的哦; - 方法名稱:get 方法;
- 方法的參數(shù):String name;
- 方法的返回值類型: String 類型的返回值。
通過如上方法特征值的共同修飾,完成了一個(gè) method_info 的存儲(chǔ),也就完成了一個(gè)方法的存儲(chǔ)。
4.屬性表計(jì)數(shù)器與屬性表
方法表后邊緊跟的是屬性表計(jì)數(shù)器,屬性表計(jì)數(shù)器后邊緊跟的結(jié)構(gòu)為屬性表。至此,Class 文件的全部結(jié)構(gòu)就講解完了。回顧之前的知識(shí),Class 文件結(jié)構(gòu)是以魔數(shù)開頭,以屬性表結(jié)尾的。
定義:屬性表計(jì)數(shù)器(attributes_count)與屬性表不可分割,這里我們對(duì)兩部分結(jié)構(gòu)一起講解。
- 屬性表計(jì)數(shù)器(attributes_count):記錄屬性表中屬性的數(shù)量,為無符號(hào)數(shù)類型。
- 屬性表(attributes):屬性表(attributes)與 Class 文件中其他的數(shù)據(jù)項(xiàng)目要求嚴(yán)格的順序、長(zhǎng)度和內(nèi)容不同,屬性表集合的限制稍微寬松一些,不再要求各個(gè)屬性表具有嚴(yán)格的順序,并且只要不與已有屬性名重復(fù),任何人實(shí)現(xiàn)的編譯器都可以向?qū)傩员碇袑懭胱约憾x的屬性信息,Java 虛擬機(jī)運(yùn)行時(shí)會(huì)忽略掉它不能識(shí)別的屬性。
Tips:學(xué)習(xí)者對(duì)屬性這一概念并不陌生了,這里不多加贅述,但是我們重點(diǎn)要關(guān)注下屬性表的兩大特點(diǎn):一個(gè)是限制寬松,無順序長(zhǎng)度要求;一個(gè)是開發(fā)者可以自己向?qū)傩员碇刑砑硬恢貜?fù)的屬性。言外之意是屬性表作為 Class 文件的一個(gè)結(jié)構(gòu),是非常靈活的,且沒有明確的長(zhǎng)度大小規(guī)定。此部分知識(shí)我們稍作了解即可。
屬性表計(jì)數(shù)器無符號(hào)數(shù)結(jié)構(gòu)示意圖:與其他計(jì)數(shù)器一樣,屬性表計(jì)數(shù)器(attributes_count)是一個(gè)無符號(hào)數(shù)結(jié)構(gòu)類型的數(shù)據(jù),u2 大小。
屬性表-表結(jié)構(gòu)類型示意圖:屬性表也是一個(gè)表結(jié)構(gòu)類型,與字段表、方法表結(jié)構(gòu)類似,但是屬性表沒有固定的長(zhǎng)度和順序限制,此處我們了解下其結(jié)構(gòu)即可。
5. 小結(jié)
本節(jié)講解了 Class 文件結(jié)構(gòu)中最后的幾種結(jié)構(gòu),分別是字段表計(jì)數(shù)器,字段表,方法表計(jì)數(shù)器,方法表,屬性表計(jì)數(shù)器,屬性表。其中字段表與方法表為本節(jié)重點(diǎn)內(nèi)容,屬性表部分視為次重點(diǎn),僅做了解即可。
至此,我們的 Class 文件結(jié)構(gòu)就講解完了,我們回顧下 Class 文件的整體結(jié)構(gòu)為:魔數(shù)->次版本號(hào)->主版本號(hào)->常量池計(jì)數(shù)器->常量池->類索引->父類索引->接口索引計(jì)數(shù)器->接口索引集合->字段表計(jì)數(shù)器->字段表->方法表計(jì)數(shù)器->方法表->屬性表計(jì)數(shù)器->屬性表。
學(xué)習(xí)者需要認(rèn)真學(xué)習(xí) Class 文件的數(shù)據(jù)結(jié)構(gòu),掌握整體結(jié)構(gòu)以及細(xì)節(jié)知識(shí)點(diǎn)。