欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java class文件格式之訪問標(biāo)志信息_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

 更新時(shí)間:2017年06月14日 14:14:42   作者:zhangjg  
access_flags 描述的是當(dāng)前類(或者接口)的訪問修飾符, 如public, private等, 此外, 這里面還存在一個(gè)標(biāo)志位, 標(biāo)志當(dāng)前的額這個(gè)class描述的是類, 還是接口

class文件中的訪問標(biāo)志信息

位于常量池下面的2個(gè)字節(jié)是access_flags 。 access_flags 描述的是當(dāng)前類(或者接口)的訪問修飾符, 如public, private等, 此外, 這里面還存在一個(gè)標(biāo)志位, 標(biāo)志當(dāng)前的額這個(gè)class描述的是類, 還是接口。access_flags 的信息比較簡(jiǎn)單, 下面列出access_flags 中的各個(gè)標(biāo)志位的信息。本來寫這個(gè)系列博客參考的是《深入java虛擬機(jī)》, 但是這本書比較老了, 關(guān)于java 5以后的新特性沒有進(jìn)行解釋,這本書中指列出了5個(gè)標(biāo)志值, 而最新的JVM規(guī)范是針對(duì)java 7 的, 其中加入了額外的三個(gè)標(biāo)志位。 分別是ACC_SYNTHETIC, ACC_ANNOTATION 和 ACC_ENUM  。

標(biāo)志名
標(biāo)志值
標(biāo)志含義
針對(duì)的對(duì)像
ACC_PUBLIC
0x0001
public類型
所有類型
ACC_FINAL
0x0010
final類型
ACC_SUPER
0x0020
使用新的invokespecial語義
類和接口
ACC_INTERFACE
0x0200
接口類型
接口
ACC_ABSTRACT
0x0400
抽象類型
類和接口
ACC_SYNTHETIC
0x1000
該類不由用戶代碼生成
所有類型
ACC_ANNOTATION 
0x2000
注解類型
注解
ACC_ENUM  
0x4000
枚舉類型
枚舉

其他標(biāo)志就不做介紹了, 這些標(biāo)志都很簡(jiǎn)單。 讀者感覺比較陌生的可能是ACC_SUPER這個(gè)標(biāo)志。 讀者會(huì)想, 類型不能被super關(guān)鍵字修飾啊, 那這個(gè)ACC_SUPER是做什么的呢?表中可以看出, 它的含義是:使用新的invokespecial語義 。 invokespecial是一個(gè)字節(jié)碼指令, 用于調(diào)用一個(gè)方法, 一般情況下, 調(diào)用構(gòu)造方法或者使用super關(guān)鍵字顯示調(diào)用父類的方法時(shí), 會(huì)使用這條字節(jié)碼指令。 這正是ACC_SUPER這個(gè)名字的由來。 在java 1.2之前, invokespecial對(duì)方法的調(diào)用都是靜態(tài)綁定的, 而ACC_SUPER這個(gè)標(biāo)志位在java 1.2的時(shí)候加入到class文件中, 它為invokespecial這條指令增加了動(dòng)態(tài)綁定的功能。 這里可能有幾個(gè)概念讀者不是很明白, 如靜態(tài)綁定, 動(dòng)態(tài)綁定等, 這些概念會(huì)在以后的博客中詳細(xì)介紹。

還有一點(diǎn)需要說明, 既然access_flags 出現(xiàn)在class文件中的類的層面上, 那么它只能描述類型的修飾符, 而不能描述字段或方法的修飾符, 希望讀者不要將這里的access_flags 和后面要介紹的方法表和字段表中的訪問修飾符相混淆。

此外, 在Java 5 的中, 引入和注解和枚舉的新特性, 那么可以推測(cè),  ACC_ANNOTATION 和 ACC_ENUM是在Java 5版本中加入的。 class文件雖然總體上保持前后一致性, 但他也不是一成不變的, 也會(huì)跟著Java版本的提升而有所改變, 但是總體來說, class文件格式還是相對(duì)穩(wěn)定的, 變動(dòng)的地方不是很多。 

class文件中的this_class

訪問標(biāo)志access_flags 下面的兩個(gè)字節(jié)叫做this_class, 它是對(duì)當(dāng)前類的描述。 它的兩個(gè)字節(jié)的數(shù)據(jù)是對(duì)常量池中的一個(gè)CONSTANT_Class_info數(shù)據(jù)項(xiàng)的一個(gè)索引。 CONSTANT_Class_info在上面的文章中已經(jīng)介紹過了。 CONSTANT_Class_info中有一個(gè)字段叫做name_index , 指向一個(gè)CONSTANT_Utf8_info , 在這個(gè)CONSTANT_Utf8_info 中存放著當(dāng)前類的全限定名。 

如果當(dāng)前類為Person:

package combjpowernodetest; 
 
public class Person { 
 
 int age; 
 
 int getAge(){ 
  return age; 
 } 
} 

將Person.class反編譯后, 可以在常量池中看到如下兩項(xiàng):

 Constant pool: 
 #1 = Class    #2    // com/bjpowernode/test/Person 
 #2 = Utf8    com/bjpowernode/test/Person 
  
......... 
......... 

這兩項(xiàng)就是當(dāng)前類的信息。 其中索引為1的CONSTANT_Class_info會(huì)被class文件中的this_class所引用。 下面給出示例圖(其中虛線范圍內(nèi)表示常量池的區(qū)域):

 

class文件中的super_class

super_class緊跟在this_class之后。 它和this_class一樣是一個(gè)指向常量池?cái)?shù)據(jù)項(xiàng)的索引。 它指向一個(gè)CONSTANT_Class_info, 這個(gè)CONSTANT_Class_info數(shù)據(jù)項(xiàng)描述的是當(dāng)前類的超類的信息。CONSTANT_Class_info中的name_index指向常量池中的一個(gè)CONSTANT_Utf8_info ,CONSTANT_Utf8_info 中存放的是當(dāng)前類的超類的全限定名。 如果沒有顯式的繼承一個(gè),也就是說如果當(dāng)前類是直接繼承Object的, 那么super_class值為0 。 我們?cè)谇懊娴奈恼轮刑岬竭^, 如果一個(gè)索引值為0, 那么就說明這個(gè)索引不引用任何常量池中的數(shù)據(jù)項(xiàng), 因?yàn)槌A砍刂械臄?shù)據(jù)項(xiàng)是從1開始的。 也就是說, 如果一個(gè)類的class文件中的super_class為0 , 那么就代表該類直接繼承Object類。 

下面以代碼來說明:

package combjpowernodetest; 
 
public class Programer extends Person{ 
 
 Computer computer; 
  
 public Programer(Computer computer){ 
  thiscomputer = computer; 
 } 
  
 public void doWork(){ 
  computercalculate(); 
 } 
} 

上面的Programer類繼承自Person類。 那么反編譯Programer .class , 它的常量池中會(huì)存在如下信息:

Constant pool: 
 
......... 
......... 
 
 #3 = Class    #4    // com/bjpowernode/test/Person 
 #4 = Utf8    com/bjpowernode/test/Person 

這兩項(xiàng)就是當(dāng)前類的父類的信息。 其中索引為3的CONSTANT_Class_info會(huì)被class文件中的super_class引用。 下面給出示例圖(其中虛線范圍內(nèi)表示常量池的區(qū)域):

class文件中的interfaces_count和interfaces

緊接著super_class的是interfaces_count, 表示當(dāng)前類所實(shí)現(xiàn)的接口的數(shù)量或者當(dāng)前接口所繼承的超接口的數(shù)量。 注意, 只有當(dāng)前類直接實(shí)現(xiàn)的接口才會(huì)被統(tǒng)計(jì), 如果當(dāng)前類繼承了另一個(gè)類, 而另一個(gè)類又實(shí)現(xiàn)了一個(gè)接口, 那么這個(gè)接口不會(huì)統(tǒng)計(jì)在當(dāng)前類的interfaces_count中。 在interfaces_count后面是interfaces, 他可以看做是一個(gè)數(shù)組, 其中的每個(gè)數(shù)組項(xiàng)是一個(gè)索引, 指向常量池中的一個(gè)CONSTANT_Class_info, 這個(gè)CONSTANT_Class_info又會(huì)引用常量池中的一個(gè)CONSTANT_Utf8_info , 這個(gè)CONSTANT_Utf8_info 中存放著有當(dāng)前類型直接實(shí)現(xiàn)或繼承的接口的全限定名。 當(dāng)前類型實(shí)現(xiàn)或繼承了幾個(gè)接口, 在interfaces數(shù)組中就會(huì)有幾個(gè)數(shù)項(xiàng)與之相對(duì)應(yīng)。 

下面看代碼示例:

package combjpowernodetest; 
 
public class Plane implements IFlyable, Cloneable{ 
 
 @Override 
 public void fly() { 
   
 } 
} 

Plane類實(shí)現(xiàn)了一個(gè)自定義的IFlyable接口, 還實(shí)現(xiàn)了一個(gè)JDK中的Cloneable接口, 那么它的常量池中會(huì)有如下信息:

Constant pool: 
 
......... 
......... 
 
 #5 = Class    #6    // com/bjpowernode/test/IFlyable 
 #6 = Utf8    com/bjpowernode/test/IFlyable 
 #7 = Class    #8    // java/lang/Cloneable 
 #8 = Utf8    java/lang/Cloneable 
  
......... 
......... 

這四項(xiàng)數(shù)據(jù)就是當(dāng)前的Plane類所實(shí)現(xiàn)的接口的信息。 第五項(xiàng)和第六項(xiàng)描述了Plane所實(shí)現(xiàn)的IFlyable接口, 第七項(xiàng)和第八項(xiàng)描述了Plane所實(shí)現(xiàn)的接口Cloneable接口。 下面是示意圖(其中虛線范圍內(nèi)表示常量池的區(qū)域):

總結(jié)

主要講解了三個(gè)部分, 分別是this_class , super_class , interfaces_count和interfaces 。 這三個(gè)數(shù)據(jù)項(xiàng)分別描述了當(dāng)前類(就是當(dāng)前class文件所在的類), 當(dāng)前類所繼承的超類, 和當(dāng)前類所實(shí)現(xiàn)的接口(如果當(dāng)前class文件代表的是一個(gè)接口, 那么 interfaces_count和interfaces描述的是當(dāng)前接口所繼承的超接口)。

這幾個(gè)數(shù)據(jù)項(xiàng)都持有指向常量池的索引。 真實(shí)的信息都是存放在常量池中的, 只不過常量池中的這些信息會(huì)被this_class , super_class , interfaces_count和interfaces 引用。

相關(guān)文章

最新評(píng)論