国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

實(shí)例探索Class文件

2019-11-14 15:25:46
字體:
供稿:網(wǎng)友

 class文件是指以.class為文件后綴的java虛擬機(jī)可裝載文件。無論該class文件是在linux上進(jìn)行編譯的,還是在windows環(huán)境下編譯的,無論虛擬機(jī)是在何種平臺(tái)下實(shí)現(xiàn)和運(yùn)行的,class文件使得Java虛擬機(jī)可以正確的讀取、解釋所有的class文件。 在分析和研究class文件之前,先提出有一些問題:

1.類/接口(class文件也可能定義的是接口,所以還是不要理解為類文件為好)內(nèi)有哪些內(nèi)容?

2.以上內(nèi)容分別保存在class文件的什么地方?

3.這些內(nèi)容在加載過程中又如何被讀取和解析?

4.這些內(nèi)容加載后又會(huì)被解析成為什么樣的數(shù)據(jù)結(jié)構(gòu)保存在虛擬機(jī)中?

5.這些數(shù)據(jù)結(jié)構(gòu)在虛擬機(jī)的運(yùn)行過程中又是如何被使用的?

擴(kuò)展問題:

6.如何防止class文件被劫持?

7.如何防止class文件被反編譯?

 

class文件的組織結(jié)構(gòu)定義如下:

ClassFile{magic                        u4,minor_version                u2,major_version                u2,constant_pool_count            u2,constant_pool                cp_info*constant_pool_count,access_flags                 u2,this_class                   u2,super_class                  u2,interface_count              u2,interfaces                   u2 * interface_count,fields_count                 u2,fields                      field_info * fields_count,methods_count                u2,methods                      method_info * methods_count,attributes_count             u2,attributes                   attributes_info * attributes_count}

以如下程序?yàn)槔瑢?duì)生成的class文件進(jìn)行分析:

 1 //TestInterface.java 2 public interface TestInterface { 3     public void interface_method(); 4 } 5  6 //TestClass.java 7 public class TestClass implements TestInterface{ 8     PRivate int private_global = 3; 9     public int public_global;10     private static final int sfi = 127;11     public static final String sfs = "test strings";12     private StringBuilder sb;13     14     public void method_1(){15         private_global = public_global * 2;16         sb.append(private_global);17     }18     19     public void method_2(int pub){20         public_global = pub;21     }22 23     public void method_2(int pub, boolean flag){24         int tmp = 5;25         public_global = pub * 2 + tmp;26     }27     28     @Override29     public void interface_method() {30         method_1();31     }32     33 }

1.magic(魔數(shù)) 值為0xcafebabe,沒有特別的意義,放在文件頭并選取用來標(biāo)記改文件是一個(gè)class文件。

 

2.minor_version/major_version(次版本號(hào)和主版本號(hào))

次版本號(hào)和主版本號(hào)分別為0x0000和0x0032(50),即主版本號(hào)位50,次版本號(hào)為0

 

3.constant_pool_count/constant_pool(常量池?cái)?shù)量和常量池)

常量池保存了文件中類或接口相關(guān)的一切常量,字面常量(直接量),如文字字符串、final變量值,以及符號(hào)引用,如類或接口的全限定名、方法或字段的簡(jiǎn)單名稱和描述符

其中,全限定名用以在當(dāng)前命名空間內(nèi)唯一標(biāo)志類或接口,在java語言中如java.lang.Object,在class文件中,會(huì)將'.'用'/'取代,即表示為java/lang/Object 簡(jiǎn)單名稱就是簡(jiǎn)單的方法名或變量名的字符串,如java.lang.Object的成員方法wait()的簡(jiǎn)單名稱為"wait"。

而只有簡(jiǎn)單名稱是無法唯一確定調(diào)用的方法是哪一個(gè),由于Java語言的特性,方法可能被重寫或重載, 所以還需要根據(jù)方法的返回值、參數(shù)數(shù)量、類型、順序來確定一個(gè)方法描述符來唯一標(biāo)志該方法,字段的描述符則簡(jiǎn)單得多,只需要給出字段的類型 描述符讓我們聯(lián)想起PE/ELF文件的函數(shù)簽名,它由上下文無關(guān)語法定義:

FieldDescriptor:            FieldTypeComponentType:            FieldTypeFieldType:            BaseType            ObjectType            ArrayTypeBaseType:            B            C            D            F            I            J            S            ZObjectType:            L<classname>;ArrayType:            [ComponentTypeMethodDescriptor:            (ParameterDescriptor*) ReturnDescriptorParameterDescriptor:            FieldTypeReturnDescriptor:            FieldType            V

其終結(jié)符號(hào)如下:

以深入java虛擬機(jī)上的示例作為參考:

     

下面看class文件內(nèi)常量池部分: 首先是常量池?cái)?shù):即(0x35)53個(gè)常量池

Java虛擬機(jī)將常量池組織成為列表(可以看做是一個(gè)常量池的數(shù)組)的形式,常量池內(nèi)容可能指向其他常量池,并且class文件中其他部分內(nèi)容也可能指向常量池入口,這些常量池通過該常量池在常量池列表中的索引來定位,常量池列表的0號(hào)常量池其實(shí)是空的,作為常量池的NULL引用,即常量池列表的第一項(xiàng)實(shí)際上是1號(hào)常量池,常量池列表實(shí)際上只有constant_pool_count - 1個(gè)常量池項(xiàng)。 隨后是常量池列表,常量池的結(jié)構(gòu)如下:

cp_info{tag,info}

常量池的固定第一個(gè)字節(jié)是常量值標(biāo)簽,用來描述該常量池保存內(nèi)容的類型,常量池標(biāo)志和含義如下:

 

根據(jù)常量池標(biāo)志tag的不同,info有不同的組織方式:

(1).CONSTANT_Utf8結(jié)構(gòu):

 

(可以看出length由2個(gè)字節(jié)表示,最大長(zhǎng)度就應(yīng)該是65536字節(jié))

該類型是一個(gè)長(zhǎng)度可變(長(zhǎng)度為length)的常量字符串表,用來存儲(chǔ)以下類型的字符串:

  • 文字字符串,如String對(duì)象的內(nèi)容
  • 當(dāng)前類或接口的全限定名
  • 當(dāng)前類的超類的全限定名
  • 當(dāng)前類或接口的父接口的全限定名
  • 字段的簡(jiǎn)單名稱或描述符
  • 方法的簡(jiǎn)單名稱或描述符
  • 引用類或接口的全限定名
  • 引用字段的簡(jiǎn)單名稱和描述符
  • 引用方法的簡(jiǎn)單名稱和描述符

字符的存放: 
對(duì)于0x0001-0x007f的字符將使用一個(gè)字節(jié)(該字節(jié)的0-6位,第7位為0)存放 
對(duì)于0x080-0x07ff的字符將使用兩個(gè)字節(jié)(依次高字節(jié)的0-5位和低字節(jié)的0-4位,剩余位分別為10、110)存放 

 

對(duì)于0x0800-0xffff的字符將使用3個(gè)字節(jié)(依次為高字節(jié)的0-5中間字節(jié)的0-5,和低字節(jié)的0-3位,剩余位分別為10、10、1110)存放。

(2).CONSTANT_Integer結(jié)構(gòu):

TypeNameCount
u4bytes1

 

 

按高位在前的格式存儲(chǔ)int型數(shù)據(jù)

(3).CONSTANT_Float結(jié)構(gòu):

TypeNameCount
u4bytes1

 

 

按高位在前的格式存儲(chǔ)float型數(shù)據(jù) 
(4).CONSTANT_Doube結(jié)構(gòu):

TypeNameCount
u8bytes1

 

 

按高位在前的格式存儲(chǔ)double型數(shù)據(jù) 
(5).CONSTANT_Long結(jié)構(gòu):

TypeNameCount
u8bytes1

 

 

按高位在前的格式存儲(chǔ)long型數(shù)據(jù) 
(6).CONSTANT_Class結(jié)構(gòu):

TypeNameCount
u2name_index1

 

 

name_index為類或者接口符號(hào)引用的CONSTANT_Utf8常量池的索引(全限定名) 
(7).CONSTANT_String結(jié)構(gòu):

TypeNameCount
u2sring_index1

 

 

string_index為字符串的CONSTANT_Utf8常量池的索引 
(8).CONSTANT_Fieldref結(jié)構(gòu): 
描述了指向字段的符號(hào)引用,其內(nèi)容分兩項(xiàng)表示,一項(xiàng)為被引用字段所在類或接口的CONSTANT_Class常量池索引,一項(xiàng)為字段的簡(jiǎn)單名稱和描述符,指向一個(gè)CONSTANT_NameAndType常量池

TypeNameCount
u2class_index1
u2name_and_type_index1

 

 

 

(9).CONSTANT_Methodref結(jié)構(gòu): 
與CONSTANT_Fieldref類似,描述了指向類中聲明的方法的符號(hào)引用,其內(nèi)容分兩項(xiàng)表示,一項(xiàng)為被引用方法所在類的CONSTANT_Class常量池索引,一項(xiàng)為方法的簡(jiǎn)單名稱和描述符,指向一個(gè)CONSTANT_NameAndType常量池

TypeNameCount
u2class_index1
u2name_and_type_index1

 

 

 

(10).CONSTANT_InterfaceMethodref結(jié)構(gòu): 
與CONSTANT_Methodref類似,描述了指向接口中聲明的方法的符號(hào)引用,其內(nèi)容分兩項(xiàng)表示,一項(xiàng)為被引用方法所在接口的CONSTANT_Class常量池索引,一項(xiàng)為方法的簡(jiǎn)單名稱和描述符,指向一個(gè)CONSTANT_NameAndType常量池

TypeNameCount
u2class_index1
u2name_and_type_index1

 

 

 

(11).CONSTANT_NameAndType結(jié)構(gòu): 
可以預(yù)見,該常量池提供了所引用字段或方法的簡(jiǎn)單名稱和常量池入口

TypeNameCount
u2class_index1
u2name_and_type_index1

 

 

 

注意區(qū)分class_index指向的是對(duì)應(yīng)類的常量池,該CONSTANT_Class常量池指向一個(gè)全限定名的CONSTANT_Utf8字符串常量池 
常量池部分的解析可以參考http://note.youdao.com/share/?id=3c1f3fac45837f95cc87fa6694a25b84&type=note 

4.access_flags 
該項(xiàng)2字節(jié)標(biāo)志了所定義類或接口的類型信息

 

該文件中access_flags為0x0021 ,可見該類是public super類型。

5.this_class(當(dāng)前類) 
該項(xiàng)2字節(jié)標(biāo)志了所定義類或接口的CONSTANT_Class常量池索引,最終指向全限定名”TestClass” 

6.super_class(超類) 
該項(xiàng)2字節(jié)標(biāo)志了所定義類的超類的CONSTANT_Class常量池索引,最終指向全限定名”java/lang/Object”

7.interfaces_count/interfaces(接口數(shù)和接口) 
首先2字節(jié)是在該類中直接實(shí)現(xiàn)或擴(kuò)展的接口數(shù),后面緊隨若干個(gè)(接口數(shù))2字節(jié),代表所直接實(shí)現(xiàn)或擴(kuò)展的接口的CONSTANT_Class常量池的索引 

這里只實(shí)現(xiàn)了一個(gè)接口,就是5號(hào)常量池,即全限定名”TestInterface”所定義的接口

8.fields_count/fields(字段數(shù)和字段) 
fields_count是類變量(靜態(tài)變量)和實(shí)例變量(非靜態(tài)變量)的字段數(shù)總和,與constant_pool組織形式類似,后面是fields_count個(gè)field_info,需要注意的是,當(dāng)前類的字段不會(huì)包含其超類或父接口中繼承的字段,也會(huì)包含在Java源文件中沒有但是在編譯時(shí)添加的一些字段。field_info結(jié)構(gòu)如下:

field_info{access_flags             u2,name_index               u2,descriptor_index         u2,attributes_count         u2,attributes               attributes_info * attributes_cout }

(1).字段的accesss_flags與描述當(dāng)前類的access_flags不同:

   

類中聲明的字段,只能擁有ACC_PUBLIC、ACC_PRIVATE、ACC_PROTECTED三個(gè)標(biāo)志中的一個(gè)。ACC_FINAL 
和ACC_VOLATILE 不能同時(shí)設(shè)置。所有接口中聲明的字段必須有ACC_PUBLIC、ACC_STATIC、ACC_FINAL 這三種標(biāo)志。 
(2).name_index為該字段的簡(jiǎn)單名稱的CONSTANT_Utf8常量池索引 
(3).descriptor_index為該字段的描述符的CONSTANT_Utf8常量池索引 
(4).attributes_count和attributes是attributes_count個(gè)attribute_info結(jié)構(gòu)所表述的屬性集合。在字段域出現(xiàn)的屬性有ConstantValue(final常量)、Deprecated(被禁用的指示符)、Synthetic(編譯器產(chǎn)生的指示符)

屬性出現(xiàn)在ClassFile、field_info、method_info、Code_attribute中。所有Java虛擬機(jī)必須能夠識(shí)別Code、ConstantValue、Exception。對(duì)于能夠正常實(shí)現(xiàn)Java/Java2平臺(tái)類庫的虛擬機(jī)必須能夠識(shí)別InnerClass和Synthetic屬性。

attribute_info的結(jié)構(gòu)如下:

attribute_info{attribute_name_index            u2,attribute_length                u4,info                            u1,}

attribute_name_index為描述屬性的字符串名稱(即上述列出屬性名)的CONSTANT_Utf8常量池索引, 
attribute_length為后面屬性內(nèi)容的長(zhǎng)度 
這里先介紹將字段可能用到的ConstantValue、Deprecated和Synthetic屬性 
(1).ConstantValue

TypeNameCount
u2constantvalue_index1

 

 

該屬性用于描述值為常量的字段,并且在包含該屬性的字段其access_flag必須為ACC_STATIC,以表明這是一個(gè)靜態(tài)常量。 
constantvalue_index指向提供常量值的常量池索引(此外,ConstantValue對(duì)應(yīng)的屬性的attribute_length始終為2) 
(2).Deprecated 
被@Deprecated所注釋的字段、方法或類型,表示雖然該字段、方法或類型仍然存在,但是不建議使用,其在未來的版本中可能會(huì)被移除 
Deprecated對(duì)應(yīng)的屬性的attribute_length值始終為0 
(3).Synthetic 
用來指明為編譯器所產(chǎn)生的字段、方法或類型 
同樣,這是一個(gè)固定長(zhǎng)度屬性,其 
對(duì)應(yīng)的屬性的attribute_length值始終為0

class文件field域解析: 
首先由開頭兩個(gè)字節(jié)看出有5個(gè)field_info 

field1: 
access_flag為ACC_PRIVATE,標(biāo)志其為private類型 
name_index為0x0007,指向7號(hào)常量池,即簡(jiǎn)單名稱為”private_global” 
descriptor_index為0x0008,指向8號(hào)常量池,即描述符為”I” 
attributes_count為0,即沒有任何屬性 

field2: 
access_flag為ACC_PUBLIC,標(biāo)志其為public類型 
name_index為0x0009,指向9號(hào)常量池,即簡(jiǎn)單名稱為”public_global” 
descriptor_index為0x0008,指向8號(hào)常量池,即描述符為”I” 
attributes_count為0,即沒有任何屬性 

field3: 
access_flag為0x0010|0x0008|0x0002,即ACC_FINAL | ACC_STATIC | ACC_PRIVATE,標(biāo)志其為private static final類型 
name_index為0x000A,指向10號(hào)常量池,即簡(jiǎn)單名稱為”sfi” 
descriptor_index為0x0008,指向8號(hào)常量池,即描述符為”I” 
attributes_count為1,即有一個(gè)屬性 

該屬性的 
attribute_name_index為0x000B,指向11號(hào)常量池,即”ConstantValue”屬性 
attribute_length為2,即固定2個(gè)字節(jié) 
constantvalue_index為0x000C,指向12號(hào)常量池,即sfi的值為”127”(這里還是字符串) 

field4: 
access_flag為0x0010|0x0008|0x0001,即ACC_FINAL | ACC_STATIC | ACC_PUBLIC,標(biāo)志其為public static final類型 
name_index為0x000D,指向13號(hào)常量池,即簡(jiǎn)單名稱為”sfs” 
descriptor_index為0x000E,指向14號(hào)常量池,即描述符為”Ljava/lang/String;” 
attributes_count為1,即有一個(gè)屬性 

該屬性的 
attribute_name_index為0x000B,指向11號(hào)常量池,即”ConstantValue”屬性 
attribute_length為2,即固定2個(gè)字節(jié) 
constantvalue_index為0x000F,指向15號(hào)常量池,即sfs的值為”test strings” 

field5: 
access_flag為ACC_PRIVATE,標(biāo)志其為private類型 
name_index為0x0011,指向17號(hào)常量池,即簡(jiǎn)單名稱為”sb” 
descriptor_index為0x0012,指向18號(hào)常量池,即描述符為”Ljava/lang/StringBuilder;” 
attributes_count為0,即沒有任何屬性 

9.methods_count/methods(方法數(shù)/方法) 
方法域的method_info結(jié)構(gòu)與字段域是一樣的,即

method_info{access_flags             u2,name_index               u2,descriptor_index         u2,attributes_count         u2,attributes               attributes_info * attributes_cout }

不過其access_flag有些不同

 

如果一個(gè)方法是抽象方法,那么它就不能為private、static、final、synchronized、native和strict類型

方法域出現(xiàn)的屬性有Code、Deprecated、Exceptions、Synthetic 
下面介紹新出現(xiàn)的兩種屬性Code和Exceptions: 
(1).Code 
其info域的結(jié)構(gòu)如下

 

其中:

  • max_stack標(biāo)志該方法執(zhí)行的任意時(shí)刻,其操作數(shù)棧的最大長(zhǎng)度(以字為單位)
  • max_locals標(biāo)志改方法的局部變量所需存儲(chǔ)空間的長(zhǎng)度(以字為單位)
  • code_length給出了該方法字節(jié)碼部分的長(zhǎng)度(以字節(jié)為單位)
  • code_length長(zhǎng)度的字節(jié)碼
  • exception_table_length是異常表的長(zhǎng)度,緊接著是exception_table_length個(gè)exception_info所描述的異常信息
  • 最后就是該段代碼的屬性描述,這是一個(gè)嵌套的屬性描述,會(huì)出現(xiàn)兩個(gè)新的屬性LineNumberTable和LocalVariableTable,即行號(hào)表和局部變量表

首先看exception_table_info的結(jié)構(gòu),可以預(yù)見,一個(gè)異常在代碼中的描述就必須包含作用域、異常類型和異常處理三部分內(nèi)容,看看exception_table_info是不是這樣組織的

exception_table_info{start_pc             u2,end_pc               u2,handler_pc           u2,catch_type           u2,}

不出所料,start_pc就是異常處理器起始位置相對(duì)該段代碼的偏移量, 
end_pc就是異常處理器結(jié)束位置相對(duì)該段代碼的偏移量, 
handler_pc就是異常處理器第一條指令相對(duì)該段代碼的偏移量 
catch_type指向描述該異常類型(java/lang/Throwable或其子類)的CONSTANT_Class常量池索引,二若catch_type為0,那么異常處理器將處理所有異常

(2).LineNumberTable 
行號(hào)表與ELF/PE文件看上去有著異曲同工之妙,它同樣建立了方法的字節(jié)碼偏移量和源代碼行號(hào)之間的映射關(guān)系。其info域結(jié)構(gòu)如下

TypeNameCount
u2line_number_table_length1
line_number_infoline_number_tableline_number_table_length

 

 

 

line_number_table_length描述了行號(hào)表的項(xiàng)數(shù),注意,并不是行號(hào)表各項(xiàng)并不是逐行對(duì)應(yīng),而是可能按照任何順序排列,并且可能多項(xiàng)對(duì)應(yīng)同一行。 
line_number_info的結(jié)構(gòu)如下:

line_number_info{start_pc           u2,line_number        u2,}

其中,start_pc描述了該行起始第一個(gè)字節(jié)碼對(duì)應(yīng)該段代碼的偏移量,line_number描述了對(duì)應(yīng)的行號(hào)。

(3).LocalVariableTable 
這里由LocalVariableTable保存了方法的棧幀中局部變量域源代碼中局部變量的名稱和描述符之間的映射關(guān)系。

 

同樣,局部變量表也是以local_variable_table_length個(gè)local_variable_info結(jié)構(gòu)進(jìn)行組織的 

local_variable_info的結(jié)構(gòu)如下:

local_variable_info{start_pc                u2,length                  u2,name_index              u2,descriptor_index        u2,index                   u2,}
  • start_pc為該段代碼中指令開始位置的便宜
  • length為從start_pc開始的、所有局部變量有效的代碼的長(zhǎng)度(即由[start_pc, start_pc + length]描述了局部變量的作用域)
  • name_index為該局部變量簡(jiǎn)單名稱的CONSTANT_Utf8常量池索引
  • descriptor_index為該局部變量描述符的CONSTANT_Utf8常量池索引
  • index為在此方法的棧幀中局部變量部分的索引 
    需要明白,local_variable_info建立了源代碼中局部變量名稱、類型和其在字節(jié)碼的作用域、以及棧幀中的索引之間的聯(lián)系,因方法區(qū)這一特殊的結(jié)構(gòu)而存在。

(4).Exceptions屬性 
區(qū)別于描述Code屬性的exception_table部分,這里是方法可能會(huì)拋出的異常,而非包圍代碼的try/catch異常。Exceptions屬性的info域格式如下:

TypeNameCount
u2number_of_exceptions1
u2exception_index_tablenumber_of_exceptions

 

 

 

exception_index_table是該方法拋出的異常類型的CONSTANT_Class常量池索引,number_of_exceptions指出了拋出異常類型的數(shù)量。 


methods部分的解析可以參考http://note.youdao.com/share/?id=b1c762ba1ee4874a23eb8a512cccf507&type=note 
10.attributes_count/attributes(屬性數(shù)和屬性) 
最后還有兩種屬性:InnerClass和SourceFile 
(1).SourceFile 
其info結(jié)構(gòu)為:

TypeNameCount
u2sourcefile_index1

 

 

給出了指向源文件名的CONSTANT_Utf8常量池索引 
如該class文件最后的attributes_count為1,其 
attribute_name_index為0x0033,指向51號(hào)常量池,即”SourceFile”屬性 
attribute_length為0x02,即2個(gè)字節(jié) 
sourcefile_index為0x0034,指向52號(hào)常量池,即源文件名為”TestClass.java”

(2).InnerClasses

TypeNameCount
u2number_of_classes1
classes_infoclassesnumber_of_classes

 

 

 

classses_info描述了內(nèi)部類(成員嵌套類、局部嵌套類和匿名嵌套類)的信息,其結(jié)構(gòu)如下:

classes_info{inner_class_info_index        u2,outer_class_info_index        u2,inner_name_index              u2,inner_class_access_flags      u2,}
  • inner_class_info_index指向所定義的內(nèi)部類的CONSTANT_Class常量池的索引
  • outer_class_info_index指向該內(nèi)部類的外圍類的CONSTANT_Class常量池的索引,若該內(nèi)部類不是一個(gè)成員嵌套類,其值為0
  • inner_name_index為該內(nèi)部類的簡(jiǎn)單名稱的CONSTANT_Utf8_info索引,當(dāng)該內(nèi)部類為匿名內(nèi)部類時(shí),其值為0
  • inner_class_access_flags是對(duì)該內(nèi)部類的訪問標(biāo)志

以如下內(nèi)容為例 
 
其生成的class文件如下: 

其InnerClasses屬性內(nèi)容為: 

其中匿名內(nèi)部類Runnable的全限定名為InnerClassTest$1,由于其不是一個(gè)成員嵌套類(該類是局部嵌套類),其outer_class_info_index 為0,由于該類是一個(gè)匿名內(nèi)部類,其inner_name_index為0(即簡(jiǎn)單名稱為空) 
局部嵌套類NestedLocalClass的全限定名為InnerClassTest$1NestedLocalClass,由于其不是一個(gè)成員嵌套類,其outer_class_info_index為0,其簡(jiǎn)單名稱為”NestedLocalClass”,access_flag為final 
成員嵌套類NestedMemberClass的全限定名為InnerClassTest$NestedMemberClass,其簡(jiǎn)單名稱為”NestedMemberClass”,access_flag為public static final

此外,我們注意到內(nèi)嵌類的內(nèi)容會(huì)定義在各自的class文件中,而不會(huì)出現(xiàn)在InnerClassTest類的class文件中,在NestedMemberClass的class文件中有著如下的InnerClasses屬性: 

在subClass的class文件中也有著如下的InnerClasses屬性: 

可以看出,每個(gè)作為外圍類的內(nèi)部類的類都將保存在該外圍類的CONSTANT_Class常量池中,并有一個(gè)inner_class_info結(jié)構(gòu)加以描述 
如InnerClassTest的3個(gè)內(nèi)部類項(xiàng),NestedMemberClass的第二個(gè)內(nèi)部類項(xiàng)
 
但是需要注意,subClass在被沒有被InnerClassTest直接引用時(shí),是不會(huì)出現(xiàn)在InnerClassTest的InnerClasses屬性中的 
另外,InnerClasses還將表述內(nèi)嵌類型的外圍類,作為內(nèi)部類的所有外圍類都將保存在該內(nèi)部類的CONSTANT_Class常量池中,并有一個(gè)inner_class_info結(jié)構(gòu)加以描述 
如NestedMemberClass的第1個(gè)外部類項(xiàng),subClass的2個(gè)外部類項(xiàng)

版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 孟村| 余姚市| 乌拉特中旗| 彭泽县| 新河县| 呼伦贝尔市| 玉门市| 铜山县| 凤山市| 洪湖市| 大余县| 法库县| 昭通市| 温州市| 卓资县| 阿拉善盟| 嘉峪关市| 冷水江市| 荔浦县| 桐梓县| 常宁市| 海阳市| 滦平县| 永福县| 三河市| 浮梁县| 达拉特旗| 汤阴县| 德昌县| 伊宁市| 丹寨县| 镇巴县| 广平县| 黄大仙区| 沙田区| 聊城市| 宁陕县| 阿图什市| 延寿县| 宜都市| 扎赉特旗|