当前位置: 首页 > 后端技术 > Java

最通俗易懂的Class文件结构(下)

时间:2023-04-01 22:30:28 Java

续上一本书续上一本书,分享Class文件的主要构成,还分析了magicnumber,minorversionnumber,major详细介绍了版本号、常量池、集合和访问标志的构建,我们接下来会继续学习。类索引和父类索引类索引(this_class)和父类索引(super_class)都是u2类型的数据。类索引用来确定这个类的全限定名,父类索引用来确定这个类的父类的全名。合格的名字。由于Java语言不允许多重继承,所以只有一个父类索引。类索引和父类索引分别指向常量池中CONSTANT_Class_info类型的类描述符,然后通过类描述符中的索引值在常量池中找到CONSTANT_Utf8_info类型的字符串。再看前面的Class文件例子:结合之前javap分析的常量池内容:#3=Class#17//OneMoreStudy#4=Class#18//java/lang/Object#17=Utf8OneMoreStudy#18=Utf8java/lang/Object类索引为0x0003,去常量池中找到索引为3的类描述符,类描述符中的索引为17,然后找到索引为17的字符串,即“OneMoreStudy”。父类索引为0x0004,到常量池中找到索引为4的类描述符,类描述符中的索引为18,再到常量池中找到索引为18的字符串,即"java/语言/对象”。接口索引集合接口索引集合(interface)是u2类型数据的集合。由于java语言允许实现多个接口,所以也有多个接口索引。它们按照implements语句后接口的顺序从左到右依次排列。在接口索引集合中。接口索引集合中的第一项数据是接口集合计数值(interfaces_count),表示有多少个接口索引。如果该类没有实现任何接口,则计数值为0,后续的接口索引表不占用任何字节。在前面的例子中,OneMoreStudy类没有实现任何接口,所以接口集合计数值为0,如下图:字段表集合字段表(field_info)用于描述接口或类中声明的变量.Includesclass-levelvariables(staticvariables)andinstance-levelvariables(membervariables),butdoesnotincludelocalvariablesdeclaredinsidemethods.Thespecificstructureisasfollows:typenamequantitydescriptionu2access_flags1fieldaccessflagu2name_index1fieldsimplenameindexu2descriptor_index1fielddescriptorindexu2attributes_count1fieldattributecountvalueattribute_infoattributesattributes_countfieldaccess_flagsintheattributefieldtableareverysimilartoclassaccess_flags,butthesignandmeaningaredifferent.具体如下表:标志名称标志值含义ACC_PUBLIC0x0001字段是否publicACC_PRIVATE0x0002字段是否privateACC_PROTECTED0x0004字段是否protectedACC_STATIC0x0008字段是否staticACC_FINAL0x0010字段是否为finalACC_VOLATILE0x0040字段是否volatileACC_TRANSIENT0x0080字段是否transientACC_SYNTHETIC0x1000字段是否由编译器自动产生的ACC_ENUM0x4000字段是否enum这里提到了简单名称、Whatisthedifferencebetweenadescriptorandafullyqualifiedname?Sayalittlebit.Asimplenameisamethodorfieldnamewithouttypeandparameterdecoration.Forexample,thesimplenamesofthenumberfieldandtheplusOne()methodintheOneMoreStudyclassare"number"and"plusOne"respectively.Thefullyqualifiednameistoreplacethe"."inthefullnameoftheclasswith"/".Forexample,thefullyqualifiednameofthejava.lang.Objectclassis"java/lang/Object".Thedescriptorisusedtodescribethedatatypeofthefield,theparameterlistofthemethod(includingquantity,typeandorder)andthereturnvalue.基本数据类型和没有return的void类型都是大写字母,对象类型用字符L加上对象的完全限定名来表示,如下表:标识字符含义B基本类型byteCbasictypecharDbasictypedoubleFbasictypefloatIbasicTypeintJBasictypelongSBasictypeshortZBasictypebooleanVSpecialtypevoidLObjecttypesuchasLjava/lang/Object对于数组类型,每个维度由一个前导的“[”字符描述,例如如java.lang.Object[][]的二维数据为“[[Ljava/lang/Object”。描述方法时,先按照参数列表的顺序描述,再返回值。参数列表严格按照顺序放在“()”值中,比如booleanequals(ObjectanObject),就是“(Ljava/lang/Object)Z”。再看前面Class文件的例子:OneMoreStudy类中只有一个字段编号,所以字段计数值为0x0001。字段号只被private修改,没有其他修改,所以该字段的访问标志为0x0002。该字段的简单名称索引为0x0005,去常量池中查找索引为5的字符串,即“number”。该字段的描述符索引为0x0006,去常量池中找到索引为6的字符串,也就是“I”,是基本类型int。以下是常量池的相关内容:#5=Utf8number#6=Utf8Ifieldnumber的属性计数值为0x0000,即没有额外的信息需要说明。从父类或父接口继承的字段不会列在字段表集合中,但可能会列出原始Java代码中没有的字段。例如,为了在内部类中保持外部类的可访问性,它会自动添加一个指向外部类实例的字段。方法表集合方法表的结构与字段表相同,也依次包括访问标志(access_flags)、名称索引(name_index)、描述符索引(descriptor_index)和属性表集合(attributes)。Thedetailsareasfollows:TypeNameQuantityDescriptionTheaccessflagoftheu2access_flags1methodThesimplenameindexoftheu2name_index1methodThedescriptorindexoftheu2descriptor_index1methodTheattributecountvalueoftheu2attributes_count1methodTheattributeoftheattribute_infoattributesattributes_countmethodFortheaccessflagsofthemethod,allflagbitsandvalues??areasfollows:标志名称标志值含义ACC_PUBLIC0x0001方法是否publicACC_PRIVATE0x0002方法是否privateACC_PROTECTED0x0004方法是否protectedACC_STATIC0x0008方法是否staticACC_FINAL0x0010方法是否为finalACC_SYNCHRONIZED0x0020方法是否sychronizedACC_BRIDGE0x0040方法是否是由编译器产生的桥接方法ACC_VARARGS0x0080方法是否接受不定参数ACC_NATIVE0x0100方法是否为nativeACC_ABSTRACT0x0400方法是否为abstractACC_STRICT0x0800WhetherthemethodisstrictfpACC_SYNTHETIC0x1000Whetherthemethodisautomaticallygeneratedbythecompiler.TheJavacodeinthemethodisprogrammedintoabytecodeinstructionbythecompilerandplacedinanattributenamed"Code"inthemethodattributetablecollection.Therewillbemorelatershare.Let’stakealookatthepreviousClassfileexampleagain:thecalculatedvalueofthemethodis0x0002,indicatingthattherearetwomethodsinthecollection(theno-argumentconstructionmethodautomaticallyaddedbythecompilerandtheplusOnemethodinthesourcecode).Theaccessflagofthefirstmethodis0x0001,indicatingthatonlytheACC_PUBLICflagistrue.Thenameindexis0x0007,andthestringwithindex7intheconstantpoolis"",whichistheno-argumentconstructionmethodautomaticallyaddedbythecompiler.Thedescriptorindexis0x0008,thestringwithindex7intheconstantpoolis"()V",theattributecountvalueofthemethodis0x0001,whichmeansthatthemethodhas1attribute,andtheattributenameindexis0x0009,whichisintheconstantpoolThestringatindex7is"Code".下面是常量池的相关内容:#7=Utf8#8=Utf8()V#9=Utf8代码属性表集合属性表(attribute_info)在之前的分享中多次出现,在Class文件中,fieldtable,methodtable可以有自己的属性表集合,用于描述特定场景下的特有信息。属性表不再要求有严格的顺序,只要不与已有的属性名重叠,任何人实现的任何编译器都可以写入自己定义的属性信息,Java虚拟机将忽略这些属性它在运行时不知道。.我总结了一些比较常用的属性,如下表所示:属性名称使用位置含义代码方法表Java代码编译字节码指令常量值字段表Final关键字定义常量值异常方法表方法异常InnerClasses类文件内部类列表LineNumberTableCodeattributeJava源代码行号和字节码指定的对应关系LocalVariableTableCode属性方法局部变量描述SourceFile类文件记录源文件名对于每个属性,其名称从常量池中引用一个CONSTANT_Utf8_info类型的常量,属性值的结构完整自定义,只需要用一个u4类型来表示属性值占用的位数。具体结构如下:typenamequantitymeaningu2attribute_name_index1属性名索引u2attribute_length1属性值位数u1infoattribute_length属性值汇总类索引、接口索引集合、字段表集合、方法表集合和属性表集合。随着JDK版本的不断升级,Class文件结构也在不断更新,学习之路永远不会停止。