实例探索class文件-java开发java经验技巧

实例探索class文件-java开发java经验技巧

ID:30887721

大小:478.19 KB

页数:21页

时间:2019-01-03

上传者:U-991
实例探索class文件-java开发java经验技巧_第1页
实例探索class文件-java开发java经验技巧_第2页
实例探索class文件-java开发java经验技巧_第3页
实例探索class文件-java开发java经验技巧_第4页
实例探索class文件-java开发java经验技巧_第5页
资源描述:

《实例探索class文件-java开发java经验技巧》由会员上传分享,免费在线阅读,更多相关内容在工程资料-天天文库

实例探索Class文件-编程开发技术实例探索Class文件原文出处:iceAeternaclass文件是指以.class为文件后缀的Java虚拟机町装载文件。无论该class文件是在linux上进行编译的,还是在windows环境下编译的,无论虚拟机是在何种平台下实现和运行的,class文件使得Java虚拟机可以正确的读取、解释所有的class文件。在分析和研究class文件之前,先提出有一些问题:1.类/接口(class文件也可能定义的是接口,所以还是不要理解为类文件为好)内有哪些内容?2.以上内容分别保存在class文件的什么地方?3.这些内容在加载过程屮又如何被读取和解析?4.这些内容加载后乂会被解析成为什么样的数据结构保存在虚拟机中?5.这些数据结构在虚拟机的运行过程•11又是如何被使用的?扩展问题:6.如何防止class文件被劫持?7.如何防止class文件被反编译?class文件的组织结构定义如下:ClassFile{magicminor_versionmajorversionconstantpoolcountconstant_poolacccss_flagsthis_classsuperclassinterfacecountinterfacesficlds_countfieldsu4,u2,u2,u2,cp_info*constant_pool_count,u2,u2,u2,u2,u2*interface_count,u2,fieldinfo*fieldscount, methods_countmethodsattributes_countattributesu2,methodinfo*methods_count,u2,attributes_info*attributes_count以如下程序为例,对生成的class文件进行分析://Testinterface,javapublicinterfaceTestinterface{???publicvoidinterface_method();//TestClass.javapublicclassTestClassimplementsTestinterface{???privateintprivate_global二3;???publicintpublic_global;???privatestaticfinalintsfi=127;???publicstaticfinalStringsfs="teststrings";???privateStringBuiIdersb;999•••???publicvoidmethodi(){???????privatc_global=public_global*2;???????sb.append(private_global);???}999•••???publicvoidmethod_2(intpub){???????public_global=pub;???}???publicvoidmethod_2(intpub,booleanflag){ ???????inttmp=5;???????public_global=pub*2+tmp;???}999•••???©Override???publicvoidinterface_method(){???????mcthod_l();???}999•••}1.magic(魔数)值为0xcafebabe,没有特别的意义,放在文件头并选取用來标记改文件是一个class文件。■QI??:CAFEBABE000000320035070002010009;|2.minor_version/major_version(次版本号和主版本号)00000000h:CAFEBABE0000003200弓5070002010009;次版本号和主版本号分别为0X0000和0X0032(50),即主版本号位50,次版本号为03.constant_pool_count/constant_pool(常量池数量和常量池)常量池保存了文件中类或接口相关的一切常量,字面常量(直接量),如文字字符串、final变量值,以及符号引用,如类或接口的全限定名、方法或字段的简单名称和描述符。其屮,全限定名用以在当前命名空间内唯一标志类或接口,在java语言屮如java.lang.Object,在class文件中,会将'•’用'/'取代,即表示为java/lang/Objcct简单名称就是简单的方法名或变量名的字符吊,如java.lang.Object的成员方法wait()的简单名称为”wait”。而只有简单名称是无法唯一确定调用的方法是哪一个,由于Java语言的特性,方法可能被重写或重载,所以还需要根据方法的返回值、参数数量、类型、顺序來确定一个方法描述符來唯一标志该方法,字段的描述符则简单得多,只需要给出字段的类型描述符让我们联想起PE/ELF文件的函数签名,它由上卜•文无关语法定义: FieldDescriptor:FieldTypeComponentType:FieldTypeFieldType:BaseTypeObjectTypeArrayTypeBaseType:BCDF 1JszObjcctTypc:L;ArrayType:[ComponentTypeMethodDescriptor:(ParameterDescriptor*)ReturnDescriptorParamctcrDcscriptor:FieldTypeReturnDescriptor:FieldType其终结符号如2终结符代表类型BbyteCcharDdoubleF基本类型终结符floatIintJlongSshortZbooleanL对象类型终结符类起始描述位置•9类结束描述位蚩[数组类型终结符数组的一维(方法描述符终结符方法起始描述位置)方法结束描述位置V返回值描述符终结符返回值为空以深入java虚拟机上的示例作为参考: 述符DescriptorFieldDeclarationI藤i;[Dlong[][]windingRoad;[Ljava/lang/Object;javag.Object[]stuff;Ljava/util/Hashtable;java.util.Hashtableht;[[[Zboolean[][][]isReady;方法描述符DescriptorMethodOiintgetSizeO;()Ljava/lang/String;StringtoString();([Ljava/lang/String;)Vvoidmain(String[]args);()Vvoidwait()(JI)Vvoidwait(longtimeout,intnanos)(ZILjava/lang/String;II)ZbooleanregionMatches(booleanignoreCase^inttoOffset,Stringother,intoc([BII)Iintread(bvte[]b,intoff,intlen);卜•面看class文件内常量池部分:首先是常量池数:即(0x35)53个常量池00000000h:CAFEBABE000000320035070002010009;Java虚拟机将常量池组织成为列农(可以看做是一个常量池的数组)的形式,常量池内容可能指向其他常量池,并且class文件中其他部分内容也可能指向常量池入口,这些常量池通过该常量池在常量池列表屮的索引来定位,常量池列农的0号常量池其实是空的,作为常量池的NULL引用,即常量池列表的第一项实际上是1号常量池,常量池列表实际上只有constant_pool_count-1个常量池项。随后是常量池列表,常量池的结构如下:cp_info{tag,info常量池的固定第一个字节是常量值标签,用来描述该常量池保存内容的类型,常量池标志和含义如下:常量表类型标志值(占1byte)描述 CONSTANTUtf81UTF-8编码的Unicode字符串CONSTANTInteger3in淡型的字面值CONSTANTFloat4flom淡型的字闻值CONSTANTLong5long类型的宁面值CONSTANTDouble6double类型的宁面值CONSTANTClass7对一个类或接口的符号引用CONSTANTString8String类型宁面值的引用CONSTANTFieldref9对一个字段的符号引用CONSTANTMethodref10对一个类中方法的符号引用CONSTANTInterfaceMethodref11对一个接口中方法的符号引用CONSTANTNameAndTvpe12对一个宇段或方法的部分符号引用根据常量池标志tag的不同,info有不同的组织方式:(l).C0NSTANT_Utf8结构:TypeNameCountU1tag1u2length1ulbyteslength(可以看岀length由2个字节表示,最大长度就应该是65536字节)该类型是一个长度可变(长度为length)的常量字符串表,用来存储以下类型的字符串:•文字字符串,如String对象的内容•当前类或接口的全限定名•当前类的超类的全限定名•当前类或接口的父接口的全限定名•字段的简单名称或描述符•方法的简单名称或描述符•引用类或接口的全限定名•引用字段的简单名称和描述符•引用方法的简单名称和描述符字符的存放:对于0x0001-0x007f的字符将使用一个字节(该字节的0-6位,第7位为0)存放对于0x080-0x07ff的字符将使用两个字节(依次高字节的0-5位和低字节的0-4位,剩余位分别为10>110)存放 byte076543210byte17654321011010987610543210对于0x0800-0xffff的字符将使用3个字节(依次为高字节的0-5中间字节的0-5,和低字节的0-3位,剩余位分别为10、10、1110)存放。bvtc1111015141312byte07654321010//10987676543210105437&/0byte276543210(2).C0NSTANT_Integer结构:TypeNameCountu4bytes1按高位在前的格式存储int烈数据(3).C0NSTANT_Float结构:TypeNameCountu4bytes1(4).CONSTANT_Doubc结构:按高位在前的格式存储float型数据TypeNameCountu8bytes1(5).CONSTANT_Long结构:按高位在前的格式存储double型数据TypeNameCountu8bytes1(6).C0NSTANT_Class结构:按高位在前的格式存储long型数据TypeNameCountu2name_index1池的索引(全限定名)name_index为类或者接口符号引用的C0NSTANT_Utf8常量(7).C0NSTANT_String结构: TypeNameCountu2sring_index1(8).C0NSTANT_Fieldref结构:string_index为字符串的C0NSTANT_Utf8常量池的索引描述了指向字段的符号引用,其内容分两项表示,一项为被引用字段所在类或接口的CONSTANT.Class常量池索引,一项为字段的简单名称和描述符,指向一个CONSTANT_NameAndType常量池(TypeNameCountu2|classindex1u2namc_and_typc_indcx1(9).CONSTANT_Methodref结构:与CONSTANT_Fieldref类似,描述了指向类中声明的方法的符号引用,其内容分两项表示,一项为被引用方法所在类的CONSTANT.Class常量池索引,一项为方法的简单名称和描述符,指向一个CONSTANT_NameAndType常量池TypeNameCountu2class_index1u2name_and_type_index1(10).CONSTANTTnterfaceMethodref结构:与CONSTANTJfethodref类似,描述了指向接I」中声明的方法的符号引用,英内容分两项表示,一项为被引用方法所在接口的CONSTANT_Class常量池索引,一项为方法的简单名称和描述符,指向一个CONSTANT_NameAndType常量池TypeNameCount|u2class_index1u2name_and_type_index1TypeNameCountJ|classindex1u2name_and_type_index1常量池部分的解析可以参考(11)・CONSTANTNamcAndTypc结构:可以预见,该常量池提供了所引用字段或方法的简单名称和常量池入口注意区分classjndex指向的是对应类的常量池,该CONSTANT.Class常量池指向一个全限定名的CONSTANT_Utf8字符串常量池http://note.youdao.com/share/?id=3cIf3fac45837f95cc87fa6694a25b84&type=note1.accessflags该项2字节标志了所定义类或接口的类型信息 标志名值设置含义设置者ACCPUBLIC0x0001public类型类和接口ACCFINAL0x0010final类型只有类会彼定义为finmlACCSUPER0x0020使用新的nvokespecia语法定义使用了invokespecia指令的类和接口ACCINTERFACE0x0200接口而非类所有接口ACCABSTRACT0x0400抽象类所有接口,部分类该文件中access_flags为0x0021,可见该类是publicsuper类型。O0»00210h:00210001000300010005000500020007:1.this_class(当前类)该项2季节标志了所定义类或接口的CONSTANT.Class常量池索引,最终指向全限定名”TestClass”[00000210h:00210001000300010005000500020007;2.super_class(超类)该项2京节标志了所定义类的超类的CONSTANT.Class常量池索引,最终指向全限定名wjava/lang/Object”00000210h:00210001000300010005000500020007;3.interfaces_count/interfaces(接口数和接|_l)首先2字节是石该类中直接实现或扩展的接口数,后面紧随若干个(接口数)2字节,代表所直接实现或扩展的接口的CONSTANT.Class常量池的索引00000210h:00210001000300010005000500020007;这里只实现了一个接口,就是5号常量池,即全限定名”Testinterface”所定义的接口&fields_count/fields(字段数和字段)field_info{access_flagsnamc_indcxdescriptorindexattributescountattributesficlds.count是类变量(静态变量)和实例变量(非静态变量)的字段数总和,与constant_pool组织形式类似,后面是fields_count个ficld_info,需耍注意的是,当前类的字段不会包含其超类或父接口"继承的字段,皿会包含在Java源文件中没有但是在编译时添加的一些字段。fieldjnfo结构如下:u2,u2,u2,u2,attributes_info*attributescout (1).字段的accesss_flags与描述当前类的access_flags不同:标志名值设置含义ACCPUBLIC0x0001public字段ACCPRIVATE0x0002privmte字段ACCPROTECTED0x0004protected宁段ACCSTATIC0x0008static^:段ACCFINAL0x0010finals段ACCVOLATILE0x0040volatile^:段ACCTRANSIENT0x0080transien学段ACCSYNTHETIC0x1000字段是否有编译器自动产生ACCTRANSIENT0x4000宁段是否是电num类屮声明的字段,只能拥有ACC_PUBLIC、ACC_PRIVATE、ACC_PROTECTED三个标志中的一个。ACC_FTNAL和ACC.VOLATILE不能同时设置。所有接I丨中芦明的字段必须有ACC_PUBLIC、ACC_STAT1C、ACC_F1NAL这三种标志。?(2).name_index为该字段的简单名称的CONSTANT_Utf8常量池索引(3).descriptor_index为该字段的描述符的CONSTANT_Utf8常量池索引(4).attributes_count和attributes是attributes_count个attribute_info结构所表述的属性集合。在字段域出现的属性有ConstantValue(final常量)、Deprecated(被禁用的指示符)、Synthetic(编译器产生的指示符)属性出现在ClassFile、field_info>method_info>Codeattribute中。所有Java虚拟机必须能够识别Code>ConstantValue^Exceptiono对于能够正常实现Java/Java2平台类库的虚拟机必须能够识别TnnerClass和Synthetic属性。属性名使用者描述Codemethodinfo方法的字节码和其他数据Constantvaluefield」nfofinml变重值Exceptionsmethodjnfo方法可能抛出的可被检测的异常InnerClassesClassFile内部类的描述LineNumberTableCodeat±ribute方法行号与宁节码的映射(行号表)LocalVariableTableCodeat±ribute方法局部变重的描述SourceFileClassFile源文件名Syntheticfieldinfozmethodjnfo编译器产生的宁段或方法的指示符Deprecatedfieldinfo。methodinfo宁段或方法被禁用的指不符attributc_info的结构如卜:attribute_info{attributenameindexu2, attributelengthu4, attribute_name_index为描述属性的字符串名称(即上述列出属性名)的CONSTANT_Utf8常量池索引,attribute_length为后而屈性内容的长度这里先介绍将字段可能用到的ConstantValue>Deprecated和Synthetic属性(1).ConstantValueTypeNameCountu2constantvalue_index1该属性用于描述值为常量的字段,并且在包含该属性的字段其acccss_flag必须为ACC_STATIC,以表明这是一个静态常量。constantvalue_index指向捉供常量值的常量池索引(此外,ConstantValue对应的属性的attributelength始终为2)?(2).Deprecated被@Deprecated所注释的字段、方法或类型,表示虽然该字段、方法或类型仍然存在,但是不建议使用,其在未來的版本中可能会被移除Deprecated对应的屈性的attributelength值始终为0(3)・Synthetic用来指明为编译器所产生的字段、方法或类型同样,这是一个固定长度属性,其对应的属性的attributc_lcngth值始终为0class文件field域解析:首先由开头两个字节看出有5个field_info00000210h:00210001000300010005000500020007:fieldl:access_flag为ACC_PRIVATE,标志其为private类型name_index为0x0007,指向7号常量池,即简单名称为”private_globalwdescriptorindex为0x0008,扌旨向8号常量池,即描述符为”I”attributescount为0,即没有任何属性00000210h:002100010003000100050005000200070O000220h:000800000001000900080000001A000Afield2:access_flag为ACC_PUBL1C,标志其为public类型nameindex为0x0009,指向9号常量池,即简单名称为”publicglobaldescriptorindex为0x0008,扌旨向8号常量池,即描述符为”I”attributes_count为0,即没有任何属性00000220h:000800000001000900080000001A000A;field3:ACC_STATICaccess_flag为0x0010|0x0008|0x0002,即ACC_FINAL ACC_PRIVATE,标志其为privatestaticfinal类型name_index为OxOOOA,指向10号常量池,即简单名称为”sfi”descriptorindex为0x0008,指向8号常量池,即描述符为”I”attributes_count为1,即有一个属性attributenameindex为OxOOOB,指向11号常量池,即”ConstantValue”属性~attribute_length为2,即固定2个字节constantvalue_index为OxOOOC,指向12号常量池,即sfi的值为”127”(这里述是字符串)0aoa0230h:00080001000B00000002000C0019000Dfield4:access_flag为0x0010|0x0008|0x0001,即ACC_FINAL|ACC_STATICACCPUBLIC,标志其为publicstaticfinal类型nameindex为OxOOOD,指向13号常量池,即简单名称为”sfs”descriptor_index为OxOOOE,指向14号常量池,即描述符为Ljava/lang/String;attributes_count为1,即有一个属性00000230h:00080001000B00W0002000C0019000D;00000240h:000E0001000B00000002000F00020011:该属性的attribute_name_index为OxOOOB,扌旨向11号常量池,即”ConstantValuen属性"attributelength为2,即固定2个字节constantvalueindex为OxOOOF,指向15号常量池,即sfs的值为”teststrings”00000240h:000E0001O00BO000O002O00F000211field5:access_flag为ACC_PRIVATE,标志其为private类型name_index为0x0011,指向17号常量池,即简单名称为”sb”descriptorindex为0x0012,指向18号常量池,即描述符为”Ljava/lang/StringBu订der;"attributes_count为0,即没冇任何属性00O00240h:0EW010BW00W020F00020011;00000250h:00120000000500010013001400010015:9.methodscount/methods(方法数/方法)方法域的method_info结构与字段域是一样的,即 u2,method_info{accessflags name_indexdescriptorindexattributescountattributesu2,u2,u2,attributes_info*attributes_cout不过其accessflag有些不同标志名值设置含义ACCPUBLIC0x0001public方法ACCPRIVATE0x0002private方法ACC_PROTECTED0x0004protected方法ACCSTATIC0x0008static方法ACCFINAL0x0010final方法ACCSYNCHRONIZED0x0020synchronizwd方法ACCNATIVE0x0100native方法ACCABSTRACT0x0400abstract^法ACCSTRICT0x0800strctFP方法如果一个方法是抽象方法,那么它就不能为private^static、final、synchronized、native和strict类型在方法域出现的属性有Code>Deprecated、Exceptions>Synthetic?卜•面介绍新出现的两种属性Code和Exceptions:(1)・Code其info域的结构如下TypeNameCountu2maxstack1u2maxjocals1u4codejength1ulcodecodejengthu2exceptiontablelength1exceptioninfoexceptiontableexception_table」engthu2at±ributescount1attributejnfoattributesat±ributescount其中:•max_stack标志该方法执行的任意时刻,其操作数栈的最人长度(以字为单位)•maxjocals标志改方法的局部变量所需存储空间的长度(以字为单位)•codejength给出了该方法字节码部分的长度(以字节为单位) •codc_lcngtht度的字节码•exception_table_length是杲常表的长度,紧接着是exception_table_length个exception_info所描述的异常信息•最后就是该段代码的屈性描述,这是一个嵌套的属性描述,会出现两个新的属性LineNumberTable和LocalVariableTable,即行号表和局部变量表首先看exception_tablc_info的结构,可以预见,一个异常在代码小的描述就必须包含作用域、异常类型和异常处理三部分内容,看看exceptiontableinfo是不是这样组织的exception_table_info{start_pcu2,cnd_pcu2,handler_pcu2,catchtypeu2,}"不出所料,start_pc就是异常处理器起始位置相对该段代码的偏移量,cnd_pc就是异常处理器结束位置相对该段代码的偏移量,handler_pc就是异常处理器第一条指令相对该段代码的偏移量catch_type指向描述该异常类型(java/lang/Throwable或其子类)的CONSTANT_Class常量池索引,二若catch_type为0,那么异常处理器将处理所有异常(2).LineNumberTable行号表与ELF/PE文件看上去有着异曲同工之妙,它同样建立了方法的字节码偏移量和源代码行号Z间的映射关系。其info域结构如下Type|NameCountu2line_number_table_length1line_number_infoline_number_tableline_number_table_lengthline_number_table_lcngth描述了彳亍号表的项数,注意,并不是行号表各项并不是逐行对应,而是可能按照任何顺序排列,并且可能多项对应同一行。1ine_number_info的结构如下:linenumberinfo{start_pcu2,line_numberu2,}"其中,start_pc描述了该行起始第一个字节码对应该段代码的偏移量,linc_numbcr描述了对应的行号。 (2).LocalVariablcTablc这里由LocalVariableTable保存了方法的栈帧屮局部变量域源代码屮局部变量的名称和描述符之间的映射关系。TypeNameCountu2localvariabletable」ength1local_variable_infolocal_variable_tablelocal_variable_table」ength同样,局部变量表也是以localvariabletablelength个localvariableinfo结构进行组织的1ocal_variable_info的结构如下:localvariableinfo{start_pcu2,lengthu2,name_indexu2,descriptor_indexu2,indexu2,}•start_pc为该段代码屮指令开始位置的便宜•length为从start_pc开始的、所冇局部变量冇效的代码的长度(即由[start_pc,start_pc+length]描述了局部变蜃的作用域)•namejndex为该局部变量简单名称的CONSTANT_UtfB常量池索引•descriptorjndex为该局部变量描述符的CONSTANT_Utf8常量池索引•index为在此方法的栈帧中局部变量部分的索引需要明fl,local_variable_info建立了源代码屮局部变量名称、类型和具在字节码的作用域、以及栈帧中的索引Z间的联系,因方法区这一特殊的结构而存在。(3).Exceptions属性TypeNameCount边numbcr_ofLcxccptions1u2exception_index_tablenumber_ofLexceptions指出了抛出杲常类型的数量。区别于描述Code屈性的exception_table部分,这里是方法可能会抛出的异常,而非包围代码的try/catch异常。Exceptions属性的info域格式如下:exceptionindextable是该方法抛出的异常类型阳CONSTAXT.Class常量池索引,number_of_exceptionsmethods部分的解析可以参考http://note.youdao.com/share/?id=blc762balee4874a23eb8a512cccf507&typc二notc9.attributescount/attributes(属性数和属性) 最后还有两种屈性:InncrClass和SourccFilc(1)・SourceFileTypeNameCountu2sourccfilc_indcx1其info结构为:给出了指向源文件名的C0NSTANT_Utf8常量池索引如该class文件最后的attributcs_count为1,其attribute_name_index为0x0033,指向51号常量池,即”SourceFile”属性attributelength为0x02,即2个字节sourcefileindex为0x0034,指向52号常量池,即源文件名TypeNameCountu2number_oLclasses1classes」nfoclassesnumber_of^classes(2).InncrClasscs为,'TestClass.java”classses_info描述了内部类(成员嵌套类、局部嵌套类和匿名嵌套类)的信息,其结构如下:classes_info{inner__class_info__indexu2,outerclassinfoindexu2,inner_name_indexu2,inner_class_access_flagsu2,}•inner_class_info_index指向所定义的内部类的CONSTANT_Class常最池的索引•outer_class_info_index指向该内部类的外围类的CONSTANT.Class常量池的索引,若该内部类不是一个成员嵌套类,其值为()•inner_name_index为该内部类的简单名称的CONSTANT_Utf8_info索引,当该内部类为匿名内部类时,其值为0•inner_class_access_flags是对该内部类的访问标,忐 以如卜'内容为例publicclassInnerClassTest{publicstaticfinalclassNestedMemberClass{finalclasssubClass{}}publicvoidedLocalClass(){finalclassNestedLocalClass{}}publicvoidnestedAnonymousClass(){newRunnabl已(){(©Overridepublicvoidrun(){}}•厂un();}}2015/8/3117:072015/8/3117:072015/8/3117:07CLASS文件CLASS文件class文件2015/8/3117:07CLASS文件其生成的class文件如下:!iInnerClassTest$l.class」InnerClassTest$lNestedLocalClass.classInnerClassTest$NestedMemberClassWsubClnss.class」InnerClassTest$NestedMemberClass.class其InncrClasscs屈性内容为:NumberofInnerClasses3inner_class=lnnerClassTest$1,inne^class^nnerClassTestSlNestedLocalClass^ame^NestedLocalClassJinalinner_class=lnnerClassTest$NestedMemberClass,outer_class=lnnerClassTest!name=NestedMemberClass!publicsta其中匿名内部类Runnable的全限定名为InnerClassTest$l,由于其不是一个成员嵌套类(该类是局部嵌套类),其outer_class_info_index为0,由于该类是一个匿名内部类,其inner_name_index为0(即简单名称为空)局部欧套类NcstcdLocalClass的全限定名为lnnerClassTest$lNestedLocalClass,由于其不是一个成员嵌套类,其outerclassinfoindex为0,其简单名称为”NestedLocalClass”,access_flag为final成员嵌套类NestedMemberClass的全限定名为InncrClassTcst$NestcdMcmbcrClass,其简单名称为”NestedMemberClass,access_flagpublicstaticfinal 此外,我们注意到内欧类的内容会定义在各口的class文件中,而不会出现在InnerClassTest类的class文件中,在NestedMemberClass的class文件屮冇着如下的InnerClasses属性:NumberofInnerClasses2inner_class=lnnerClassTest$NestedMemberClass,outer_class=lnnerClassTestfname=NestedMemberClass,publicsiinner_class=lnnerClassTest$NestedMemberClass$subClass,outer_class=lnnerClassTest$NestedMemberClassfnan在subClass的class文件中也有着如下的InnerClasses属性:NumberofInnerClasses2inner_class=lnnerClassTest$NestedMemberClass,outer_class=lnnerClassTestlname=NestedMemberClasslpublicstsinner_class=lnnerClassTest$NestedMemberClass$sut>Classfouter_class=lnnerClassTest$NestedMemberClasslnam(可以看出,每个作为外围类的内部类的类都将保存在该外围类的CONSTANT_Class常量池中,并有一个inner_class_info结构加以描述如InnerClassTest的3个内部类项,NestedMemberClass的第二个内部类项?但是需要注意,subClass在被没有被InnerClassTest直接引用时,是不会出现在InnerClassTest的InnerClasses属性中的将保存在该内部类的CONSTANT_Class常量池中,并有一个inner_class_info结构加以描述如NestedMemberClass的第1个外部类项,subClass的2个外部类项另外,InnerClasses还将表述内嵌类型的外围类,作为内部类的所有外围类都

当前文档最多预览五页,下载文档查看全文

此文档下载收益归作者所有

当前文档最多预览五页,下载文档查看全文
温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,天天文库负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。
大家都在看
近期热门
关闭