深入理解 JVM Class文件格式(二)
**
class文件中的特殊字符串
**
特殊字符串是常量池中符號(hào)引用的一部分,包括三種: 類的全限定名, 字段和方法的描述符, 特殊方法的方法名。 下面我們就分別介紹這三種特殊字符串。
(1) 類的全限定名
在常量池中, 一個(gè)類型的名字并不是我們?cè)谠次募锌吹降哪菢?#xff0c; 也不是我們?cè)谠次募惺褂玫陌宇惷男问健?源文件中的全限定名和class文件中的全限定名不是相同的概念。 源文件中的全新定名是包名加類名, 包名的各個(gè)部分之間,包名和類名之間, 使用點(diǎn)號(hào)分割。 如Object類, 在源文件中的全限定名是java.lang.Object 。 而class文件中的全限定名是將點(diǎn)號(hào)替換成“/” 。 例如, Object類在class文件中的全限定名是 java/lang/Object 。 如果讀者之前沒有接觸過class文件格式, 是class文件格式的初學(xué)者, 在這里不必知道全限定名在class文件中是如何使用的, 只需要知道, 源文件中一個(gè)類的名字, 在class文件中是用全限定名表述的。
(2) 描述符
我們知道在一個(gè)類中可以有若干字段和方法, 這些字段和方法在源文件中如何表述, 我們?cè)偈煜げ贿^了。 既然現(xiàn)在我們要學(xué)習(xí)class文件格式, 那么我們就要問, 一個(gè)字段或一個(gè)方法在class文件中是如何表述的? 在本文中, 我們會(huì)討論方法和字段在class文件中的描述。 方法和字段的描述符并不會(huì)把方法和字段的所有信息全都描述出來, 畢竟描述符只是一個(gè)簡(jiǎn)單的字符串。
在講解描述符之前, 要先說明一個(gè)問題, 那就是所有的類型在描述符中都有對(duì)應(yīng)的字符或字符串來對(duì)應(yīng)。 比如, 每種基本數(shù)據(jù)類型都有一個(gè)大寫字母做對(duì)應(yīng), void也有一個(gè)大寫字符做對(duì)應(yīng)。 下表是void和基本數(shù)據(jù)類型在描述符中的對(duì)應(yīng)。
基本上都是以類型的首字符變成大寫來對(duì)應(yīng)的, 其中l(wèi)ong和boolean是特例, long類型在描述符中的對(duì)應(yīng)字符是J, boolean類型在描述符中的對(duì)應(yīng)字符是Z 。
基本類型和void在描述符中都有一個(gè)大寫字符和他們對(duì)應(yīng), 那么引用類型(類和接口,枚舉)在描述符中是如何對(duì)應(yīng)的呢? 引用類型的對(duì)應(yīng)字符串(注意, 引用類型在描述符中使用一個(gè)字符串做對(duì)應(yīng)) , 這個(gè)字符串的格式是:
“L” + 類型的全限定名 + “;”
注意,這三個(gè)部分之間沒有空格, 是緊密排列的。 如Object在描述符中的對(duì)應(yīng)字符串是: Ljava/lang/Object; ; ArrayList在描述符中的對(duì)應(yīng)字符串是: Ljava/lang/ArrayList; ; 自定義類型com.example.Person在描述符中的對(duì)應(yīng)字符串是: Lcom/example/Person; 。
我們知道, 在Java語言中數(shù)組也是一種類型, 一個(gè)數(shù)組的元素類型和他的維度決定了他的類型。 比如, 在 int[] a 聲明中, 變量a的類型是int[] , 在 int[][] b 聲明中, 變量b的類型是int[][] , 在 Object[] c 聲明中, 變量c的類型是Object[] 。既然數(shù)組是類型, 那么在描述符中, 也應(yīng)該有數(shù)組類型的對(duì)應(yīng)字符串。 在class文件的描述符中, 數(shù)組的類型中每個(gè)維度都用一個(gè) [ 代表, 數(shù)組類型整個(gè)類型的對(duì)應(yīng)字符串的格式如下:
若干個(gè)“[” + 數(shù)組中元素類型的對(duì)應(yīng)字符串
下面舉例說明:
int[]類型的對(duì)應(yīng)字符串是: [I 。 int[][]類型的對(duì)應(yīng)字符串是: [[I 。 Object[]類型的對(duì)應(yīng)字符串是:
[Ljava/lang/Object; 。 Object[][][]類型的對(duì)應(yīng)字符串是: [[[Ljava/lang/Object; 。
介紹完每種類型在描述符中的對(duì)應(yīng)字符串, 下面就開始講解字段和方法的描述符。
字段的描述符就是字段的類型所對(duì)應(yīng)的字符或字符串。 如: int i 中, 字段i的描述符就是 I 。 Object o中, 字段o的描述符就是 Ljava/lang/Object; 。 double[][] d中, 字段d的描述符就是 [[D 。
方法的描述符比較復(fù)雜, 包括所有參數(shù)的類型列表和方法返回值。 它的格式是這樣的:
(參數(shù)1類型 參數(shù)2類型 參數(shù)3類型 …)返回值類型
其中, 不管是參數(shù)的類型還是返回值類型, 都是使用對(duì)應(yīng)字符和對(duì)應(yīng)字符串來表示的, 并且參數(shù)列表使用小括號(hào)括起來, 并且各個(gè)參數(shù)類型之間沒有空格, 參數(shù)列表和返回值類型之間也沒有空格。
下面舉例說明(此表格來源于《深入Java虛擬機(jī)》)。
(3) 特殊方法的方法名
首先要明確一下, 這里的特殊方法是指的類的構(gòu)造方法和類型初始化方法。 構(gòu)造方法就不用多說了, 至于類型的初始化方法, 對(duì)應(yīng)到源碼中就是靜態(tài)初始化塊。 也就是說, 靜態(tài)初始化塊, 在class文件中是以一個(gè)方法表述的, 這個(gè)方法同樣有方法描述符和方法名。
類的構(gòu)造方法的方法名使用字符串 表示, 而靜態(tài)初始化方法的方法名使用字符串 表示。 除了這兩種特殊的方法外, 其他普通方法的方法名, 和源文件中的方法名相同。
總結(jié)
到此為止, 關(guān)于特殊字符串就講解完了。 最后做一下總結(jié):
class文件中的特殊字符串包括類(包括接口, 枚舉)的全限定名, 字段的描述符和方法的描述符。 其中類的全限定名比較簡(jiǎn)單易于理解, 字段和方法的描述符由于涉及到每種類型的映射, 可能稍顯復(fù)雜。 要理解描述符, 主要是要熟記每種類型(包括8種基本數(shù)據(jù)類型,類類型, 數(shù)組類型和void)在描述符中所對(duì)應(yīng)的描述字符或字符串。
還有一點(diǎn)需要注意, 就是方法和字段的描述符中, 不包括字段名和方法名, 字段描述符中只包括字段類型, 方法描述符中只包括參數(shù)列表和返回值類型。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的深入理解 JVM Class文件格式(二)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 台积电10月份营收75亿美元创新高 同比
- 下一篇: Meta 工程师:明年全球 AI 推理用