溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何理解Java Class文件常量池

發(fā)布時(shí)間:2021-11-20 15:33:01 來(lái)源:億速云 閱讀:195 作者:柒染 欄目:大數(shù)據(jù)

這篇文章將為大家詳細(xì)講解有關(guān)如何理解Java Class文件常量池,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

Class文件的存在使得不同語(yǔ)言編寫(xiě)的程序都可以運(yùn)行在Java虛擬機(jī)上,只需要這些語(yǔ)言經(jīng)過(guò)編譯器編譯后的Class文件符合Java虛擬機(jī)定義的規(guī)范,Java虛擬機(jī)就可以加載執(zhí)行這些Class文件。如下圖所示:

如何理解Java Class文件常量池  


Class文件是一組以8位字節(jié)為基礎(chǔ)單位的二進(jìn)制流,各個(gè)數(shù)據(jù)項(xiàng)目嚴(yán)格按照順序緊湊地排列在Class文件中,當(dāng)遇到需要占用8個(gè)字節(jié)以上空間的數(shù)據(jù)是,則按照大端序的方式分割成若干個(gè)8位字節(jié)進(jìn)行存儲(chǔ)。

Class文件中只存在兩種數(shù)據(jù)類型:

  • 無(wú)符號(hào)數(shù)

無(wú)符號(hào)數(shù)屬于基本數(shù)據(jù)類型,以u(píng)1、u2、u4、u8分別表示1個(gè)、2個(gè)、4個(gè)和8個(gè)字節(jié)的無(wú)符號(hào)數(shù),無(wú)符號(hào)數(shù)可以用來(lái)描述數(shù)字、索引引用、數(shù)量值或者按照UTF-8編碼構(gòu)成的字符串值。

表是由無(wú)符號(hào)數(shù)和其他表組成的數(shù)據(jù)結(jié)構(gòu),所有的表都以_info結(jié)尾。

當(dāng)在描述一個(gè)可變長(zhǎng)度的類型數(shù)據(jù)時(shí),通常會(huì)采用一個(gè)容量計(jì)數(shù)器和若干個(gè)數(shù)據(jù)項(xiàng)的格式。

如何理解Java Class文件常量池  
public class ClassTest {
   private int m;
   private int inc() {        return m + 1;    }}
 

下面我們會(huì)通過(guò)上面這段代碼來(lái)分析Class文件的內(nèi)容。

如何理解Java Class文件常量池  


上面這張圖是經(jīng)過(guò)編譯后的Class文件中的內(nèi)容

 
魔數(shù)(magic)與版本號(hào)

Class文件開(kāi)頭固定的4個(gè)字節(jié)為魔數(shù),唯一作用就是用來(lái)確定這個(gè)文件是否是一個(gè)能被虛擬機(jī)接收的class文件。Java的魔數(shù)固定為0xCAFEBABE,接下去的兩個(gè)字節(jié)代表次要版本號(hào),再下去的兩個(gè)字節(jié)是主版本號(hào),主版本號(hào)為0x0034(十進(jìn)制是52,也就是JDK1.8),高版本的JDK能夠運(yùn)行以前版本的Class文件,但是不能運(yùn)行以后版本的Class文件,通俗一點(diǎn)將就是向下兼容。

 
常量池

走過(guò)了魔數(shù)和版本,接下去是Class文件中最關(guān)鍵的部分常量池,常量池由一個(gè)計(jì)數(shù)池和具體的常量項(xiàng)來(lái)組成,在我們代碼中常量池?cái)?shù)量為0x0013(十進(jìn)制是19),關(guān)于常量池的計(jì)數(shù)池有一個(gè)比較特殊的地方就是他是從1開(kāi)始計(jì)數(shù)的,也就是說(shuō)如果我們計(jì)數(shù)池的值是19,實(shí)際上是只有18個(gè)常量項(xiàng)。

常量池中主要存放兩大類常量:

  • 字面量
  • 符號(hào)引用

字面量主要指的是文本字符串、聲明為final的常量值等

符號(hào)引用主要包含三類常量:

  • 類和接口的全限定名
  • 字段的名稱和描述符
  • 方法的名稱和描述符

Java代碼在編譯的時(shí)候不存在連接時(shí),也就是Class文件中不會(huì)保存各個(gè)方法、字段的最終內(nèi)存布局信息,這些字段、方法的符號(hào)引用如果在運(yùn)行期不進(jìn)行轉(zhuǎn)換則得不到真正的內(nèi)存入口地址,所以在虛擬機(jī)運(yùn)行時(shí),需要從常量池獲得對(duì)應(yīng)的符號(hào)引用,在類創(chuàng)建和運(yùn)行時(shí)解析翻譯到具體的內(nèi)存地址中。

目前常量池中主要有以下表項(xiàng):如何理解Java Class文件常量池

這些表都會(huì)有一個(gè)固定的字段也就是開(kāi)始的第一個(gè)字節(jié)都是一個(gè)標(biāo)志位代表相應(yīng)的類型,如上圖。

大家可以通過(guò)javap -verbose xxx.class列出文件字節(jié)碼的內(nèi)容如何理解Java Class文件常量池

通過(guò)比較javap -verbose常量池的項(xiàng)的索引和我們class文件二進(jìn)制的表示可以發(fā)現(xiàn)是一一對(duì)應(yīng)的。

關(guān)于如何理解Java Class文件常量池就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI