Class 文件的訪問標(biāo)志與索引
1. 前言
本節(jié)內(nèi)容主要是介紹 Class 文件結(jié)構(gòu)中的訪問標(biāo)志與索引,其中索引又細(xì)分為類索引、父類索引、接口索引計(jì)數(shù)器、接口索引集合四個(gè)知識點(diǎn)。本節(jié)主要知識點(diǎn)如下:
- 訪問標(biāo)志的定義及意義,以及結(jié)構(gòu)示意圖,為本節(jié)重點(diǎn)內(nèi)容之一;
- 訪問標(biāo)志的標(biāo)記類型及標(biāo)記值對應(yīng)表,為本節(jié)的次重點(diǎn)內(nèi)容;
- 類索引、父類索引、接口索引計(jì)數(shù)器、接口索引集合的定義及示意圖,為本節(jié)內(nèi)容之一。
本節(jié)的索引過程講解對于初學(xué)者來說會有一定的難度,講解過程也會涉及到之前所學(xué)習(xí)的常量池知識,學(xué)習(xí)者需要結(jié)合之前所學(xué)知識去理解索引,并進(jìn)一步的加深對常量池的認(rèn)識。
2. 訪問標(biāo)志(access_flags)
Tips:前文在講解常量池部分的最后提出過問題,Class文件結(jié)構(gòu)的常量池后邊緊跟的是什么結(jié)構(gòu)呢?訪問標(biāo)志,就是我們尋求的答案。
定義:在常量池結(jié)束之后,緊接著的 2 個(gè)字節(jié)代表訪問標(biāo)志(access_flags),訪問標(biāo)志用于識別一些類或接口層次的訪問信息。
從定義的描述中我們可以了解到,訪問標(biāo)志也是無符號數(shù)類型的數(shù)據(jù),既然訪問標(biāo)志占用了 2 個(gè)字節(jié),那么訪問標(biāo)志的占用空間也可用 u2 來表示。
無符號數(shù)結(jié)構(gòu)示意圖:
從上圖中,我們能夠清晰的看到訪問標(biāo)志占用了 2 個(gè)字節(jié),是類似于我們之前所學(xué)習(xí)的常量池計(jì)數(shù)器的,因?yàn)槌A砍赜?jì)數(shù)器也是占用了 2 個(gè)字節(jié),均為 u2 大小。
3. 訪問標(biāo)志類型對應(yīng)表
這部分內(nèi)容為次重點(diǎn)內(nèi)容,通過對這部分的學(xué)習(xí),學(xué)習(xí)者需要了解訪問標(biāo)志的不同類型,以及不同類型的訪問標(biāo)志的意義。我們先來看下對應(yīng)表,后續(xù)我會舉例說明。
標(biāo)志類型 | 對應(yīng)標(biāo)志值 | 標(biāo)志意義 |
---|---|---|
ACC_PUBLIC | 0x0001 | 是否為 public 類型 |
ACC_FINAL | 0x0010 | 是否被聲明為 final 類型 |
ACC_SUPER | 0x0020 | 是否允許使用 invokespcial 字節(jié)碼指令的新語義 |
ACC_INTERFACE | 0x0200 | 標(biāo)識這是一個(gè)接口 |
ACC_ABSTRACT | 0x0400 | 是否為抽象類型 |
ACC_SYNTHETIC | 0x1000 | 標(biāo)識這個(gè)類并非由用戶代碼生成 |
ACC_ANNOTATION | 0x2000 | 標(biāo)識這是一個(gè)注解 |
ACC_ENUM | 0x4000 | 標(biāo)識這是一個(gè)枚舉 |
我們舉個(gè)簡單的例子來理解下訪問標(biāo)志以及這張對應(yīng)表。假設(shè)需要訪問一個(gè)接口,那么此時(shí)訪問標(biāo)志 ACC_INTERFACE 的值為 true,標(biāo)志對應(yīng)的值為 0x0200。這樣 JVM 虛擬機(jī)在處理訪問的時(shí)候,就能夠做到有據(jù)可依。
4. 類索引與父類索引
定義:類索引(this_class)和父類索引(super_class)都是一個(gè) u2 大小的數(shù)據(jù)。
- 類索引:確定當(dāng)前類的全限定名。
- 父類索引:確定當(dāng)前類的父類的全限定名。
Tips:由于 Java 單繼承的原則,父類只可能有一個(gè);由于 Object 是所有其他類的基類,所以除了 Object 類沒有父類以外,其余所有類的 super_class 都不為空。
無符號數(shù)結(jié)構(gòu)示意圖:類索引是緊跟在訪問標(biāo)志之后的結(jié)構(gòu),類索引后邊緊跟的結(jié)構(gòu)是父類索引。由于類索引與父類索引關(guān)系非常緊密,都是描述的當(dāng)前類以及當(dāng)前類的父類的全限定名,所以此處我們將二者放在一起進(jìn)行講解。
5. 接口索引計(jì)數(shù)器與接口索引集合
父類索引后邊緊跟的是接口索引計(jì)數(shù)器,接口索引計(jì)數(shù)器后邊緊跟的是接口索引集合。類似于常量池計(jì)數(shù)器和常量池的關(guān)系,接口索引計(jì)數(shù)器記錄的是接口索引集合中接口索引的數(shù)量。
Tips:對于常量池計(jì)數(shù)器和常量池,一個(gè)是無符號數(shù)類型,一個(gè)是表類型。相比而言,接口索引計(jì)數(shù)器和接口索引集合皆為無符號數(shù)類型,這里學(xué)習(xí)者可以進(jìn)行對比記憶。我們繼續(xù)來看下兩者的定義以及無符號數(shù)類型的結(jié)構(gòu)示意圖。
定義:
- 接口索引計(jì)數(shù)器:代表了接口索引集合中接口的數(shù)量;
- 接口索引集合:按照當(dāng)前類 implements(或當(dāng)前接口extends)的接口的順序,從左到右依次排列在接口索引集合中,此部分集合稱為接口索引集合。
無符號數(shù)結(jié)構(gòu)示意圖:接口索引計(jì)數(shù)器和接口索引集合均為無符號數(shù)類型結(jié)構(gòu),結(jié)構(gòu)示意圖如下圖所示。
從圖中可以看出,接口索引計(jì)數(shù)器占用了 2 個(gè)字節(jié),為 u2 大小,接口索引集合中的每一個(gè)接口元素占用了 2 個(gè)字節(jié)大小,也為 u2 大小。
Tips:接口索引集合后邊緊跟的數(shù)據(jù)結(jié)構(gòu)是什么?我們繼續(xù)拋出問題,后續(xù)章節(jié)會有問題的解答,讓我們帶著問題繼續(xù)探究 Class 文件結(jié)構(gòu)。
6. 小結(jié)
本節(jié)講解了 Class 文件結(jié)構(gòu)中的訪問標(biāo)志與索引,其中索引我們又細(xì)分了四部分結(jié)構(gòu)進(jìn)行了講解,分別是類索引,父類索引,接口索引計(jì)數(shù)器以及接口索引集合。通過本節(jié)的學(xué)習(xí),我們了解了它們的定義及意義,也了解了它們的數(shù)據(jù)類型及示意圖。
本節(jié)我們也拋出了問題,接口索引集合后邊緊跟的結(jié)構(gòu)是什么?我們會在下篇課程中進(jìn)行講解。本節(jié)所了解到的訪問標(biāo)志與索引相關(guān)知識均為重點(diǎn)內(nèi)容,學(xué)習(xí)者需要用心掌握。