Class文件格式(2)-深入理解ClassFile

1.access_flags

    继常量池之后,紧随着的两个字节代表当前类或者接口的访问控制权限,具体如下:
Class文件格式(2)-深入理解ClassFile_第1张图片

    1.1、ACC_SYNTHETIC

        表示当前类的是由编译器生成,而不是由用户编写的程序源代码经过编译器编译生成。

    1.2、ACC_ENUM

        当前类或者当前类的父类被声明为枚举类型。

    1.3、ACC_INTERFACE

        表示一个接口类型,如果未被设置,表示该Class文件为一个类类型。如果ACC_INTERFACE标志被设置,则ACC_ABSTRACT标志也应该被设置,同时不能够设置ACC_FINAL、ACC_SUPPER、ACC_ENUM标志。

    1.4、ACC_ANNOTATION

        标志一个注解类型。如果ACC_ANNATATION被设置,则ACC_INTERFACE标志也必须被设置。

    1.5、ACC_SUPER

        标志invokespecial指令具体使用哪种语义(invokespecial指令有两种语义),目前的JVM都应该设置这个标记。在JDK1.0.2中,Class文件的access_flags中并没有ACC_SUPER标志。

2.this_class

    this_class为一个u2类型的整数,指向常量池的一个有效索引,该索引处存放CONSTANT_Class_info结构项,描述当前类或者接口的信息,具体如下:

3.super_class

    对于一个类来说,super_class的值要么为0,要么是一个u2类型的整数值,该值为常量池的一个有效索引,该索引处存放CONSTANT_Class_info结构项,该结构项用于描述当前Class文件中定义的类的直接父类信息。同时,当前类的直接父类以及其间接父类的Class文件中的access_flags中都不能够有ACC_FINAL标志。
    如果super_class的值为0,则当前Class文件只能够是java.lang.Object类的Class文件,java.lang.Object类是唯一没有父类的类。
    对于一个接口的Class文件来说,super_class必须为一个有效的常量池索引,该索引处存放CONSTANT_Class_info结构项,该结构项描述java.lang.Object类信息。

4.interface_count

    该值为u2类型的无符号整数,表示当前类或者接口的直接父接口的个数。

5.interfaces[]

    接口数组或者接口表,数组中的每个元素为u2类型的无符号整数,表示常量池的有效索引,索引处存放CONSTANT_Class_info结构项,描述当前类或者接口的直接父接口信息。接口在interface[]数组中的出现顺序与源代码中给的接口顺序保持一致,也即,interfaces[0]对应源代码中最左边的接口。具体如下:

6.fields_count

    字段计数器,为u2类型的整数,fields_count表示当前Class文件字段表fields[]数组的成员个数。

7.fields[]

    字段表,用于描述在当前类或者接口中声明的所有字段(类变量、实例变量)信息,不包括从父接口或者父类中继承而来的部分,表中的每个成员都是field_info结构项, 具体如下:

    其中,field_info结构项用于对Class文件中的字段进行描述,field_info结构项的具体结构如下所示:
Class文件格式(2)-深入理解ClassFile_第2张图片

    7.1、access_flags

          标志该字段的访问控制权限和属性的掩码,其取值范围和意义如下表所示:
Class文件格式(2)-深入理解ClassFile_第3张图片
          如果字段的access_flags掩码中有ACC_SYNTHETIC被标记,则表明该字段是由编译器自动生成的字段,不会出现在源代码中。如果access_flags掩码中有ACC_ENUM被标记,则表明该字段的值为一个枚举类型的成员。
          字段可以同时拥有上表中的多种属性,但某些属性是互斥的,比如最多只能够拥有ACC_PRIVATE、ACC_PROTECTED、ACC_PUBLIC属性中的一个,也不能够同时拥有ACC_FINAL、ACC_VOLATILE属性。
    在Interface中的所有字段都必须拥有ACC_PUBLIC、ACC_STATIC、ACC_FINAL属性,也可能还拥有ACC_SYNTHETIC属性,除此之外,不能够拥有上表中的其他属性值。

    7.2、name_index

          指向常量池中一个合法的索引,在该索引处存放CONSTANT_Utf8_info的 常量项,代表有效字段的非全限定名。

    7.3、descriptor_index

          指向常量池中一个合法的索引,在该索引处存放CONSTANT_Utf8_info的 常量项,代表有效字段的描述符。

    7.4、attributes_count

          表示当前字段附加属性的个数。

    7.5、attributes[]

        表示当前字段的属性表,表中的每个元素均为attribute_info结构项。attribute_info结构项用于描述一个具体的属性值,attribute_info结构项的具体内容,本文后续会抽专门的章节进行讲解,在此不做过多的描述。
        在官方提供的JVMS7(Java虚拟机规范)中,规定,能够出现在field_info结构项的属性表(attributes[])中的属性种类有:ConstantValue、Synthetic、Signature 、Deprecated 、RuntimeVisibleAnnotations、RuntimeInvisibleAnnotations,如下所示:
Class文件格式(2)-深入理解ClassFile_第4张图片
       JVMS7规定,JVM的实现必须能够识别并正确的读取field_info结构项的属性表(attributes[])中的ConstantValue属性。 如果JVM的实现支持49.0或者更高版本的Class文件,则该JVM必须能够从版本号为49.0或者更高的Class文件中识别并正确读取field_info结构项的属性表(attributes[])中的如下属性项:Signature、RuntimeVisibleAnnotations、RuntimeInvisibleAnnotations 。     

8.methods_count

    方法计数器,u2类型的整数,表示当前Class文件的方发表methods[]数组的成员个数。

9.methods[]

    方法表数组,描述类中的所有方法,包括实例初始化方法和类初始化方法,   methods[]方法表仅仅描述当前类的所有方法,但是不描述从父类或者父接口中继承的方法, methods[]方法表 中的每个成员都是method_info结构项, method_info 结构项用于完整描述当前类或者接口中的一个方法。 具体如下:

    method_info描述在当前类或者接口中所声明的所有方法,包括实例方法、类方法、实例初始化方法、类或者接口的初始化方法,method_info结构项的具体结构如下所示:
Class文件格式(2)-深入理解ClassFile_第5张图片

    9.1、access_flags

          标志当前有method_info所描述的方法的访问控制权限和属性的掩码,其取值范围和意义如下表所示:
Class文件格式(2)-深入理解ClassFile_第6张图片
        ACC_VARARGS标志表示方法在源代码级别为带有变长参数的方法。
        ACC_BRIDGE标志表示该方法是Java编译器生成的bridge方法。
        ACC_SYNTHETIC标志表示该方法是由编译器生成的方法,该方法不会出现在程序的源代码中,当然也有某些方法例外,这些例外可参加JVMS7的Methods章节和Synthetic属性章节。
        Class的方法可以同时拥有上表中的多个属性值,但某些属性是互斥的,比如,最多只能够拥有ACC_PRIVATE、ACC_PROTECTED、ACC_PUBLIC中的一个属性,如果access_flags设置了ACC_ABSTRACT属性,则该方法就不能够设置ACC_FINAL、ACC_NATIVE、 ACC_PRIVATEACC_STATICACC_STRICT 、 ACC_SYNCHRONIZED属性。
        Interface的所有方法,都必须设置ACC_ABSTRACT和ACC_PUBLIC属性,这些接口方法或许还有ACC_VARARGS、ACC_BRIDGE、ACC_SYNTHETIC属性,除此之外,不能够拥有上表中的其它属性。
        对于实例初始化方法,可以拥有ACC_PRIVATEACC_PROTECTEDACC_PUBLIC三者之一,还可以拥有 ACC_STRICTACC_VARARGS、 ACC_SYNTHETIC属性,除此之外,实例初始化方法不能够拥有上表中的其它属性。
        对于类或者接口的初始化方法,它们由Java虚拟机隐式的调用,这些方法中,除了ACC_STRICT外,其余属性都将被忽略。

    9.2、name_index

          指向常量池中一个合法的索引,在该索引处存放CONSTANT_Utf8_info的 常量项,要么表示一个初始化方法(),要么表示方法的有效非全限定名。

    9.3、descriptor_index

          指向常量池中一个合法的索引,在该索引处存放CONSTANT_Utf8_info的 常量项,代表有效方法的描述符。

    9.4、attributes_count

          表示当前方法附加属性的个数。

    9.5、attributes[]

          表示当前方法的属性表,同field_info结构项的属性表一样,method_info属性表中的每个元素也均为attribute_info结构项,在此不做过多的描述。
        在官方提供的JVMS7(Java虚拟机规范)中,规定,能够出现在method_info结构项的属性表(attributes[])中的属性种类有: Code、   Exceptions、 Synthetic 、 Signature、   Deprecated、 RuntimeVisibleAnnotations、   RuntimeInvisibleAnnotations、   RuntimeVisibleParameterAnnotations、 RuntimeInvisibleParameterAnnotations、 AnnotationDefault  ,如下所示:
Class文件格式(2)-深入理解ClassFile_第7张图片
        JVMS7规定,JVM的实现必须能够识别并正确的读取method_info结构项的属性表(attributes[])中的Code、Exceptions属性。如果JVM的实现支持49.0或者更高版本的Class文件,则该JVM必须能够从版本号为49.0或者更高的Class文件中识别并正确读取method_info结构项的属性表(attributes[])中的如下属性项:Signature、RuntimeVisibleAnnotations、RuntimeInvisibleAnnotations、RuntimeVisibleParameterAnnotations、RuntimeInvisibleParameterAnnotations、AnnotationDefault 。   

10.attributes_count

    属性计数器,u2类型的整数,表示Class文件所描述类的属性数组attributes[]的成员个数。

11.attributes[]

     当前Class文件属性表, 属性表中的每个元素都是attribute_info结构项

    11.1、attribute_info

         attribute_info结构项在 ClassFile的属性表、field_info结构项的属性表、method_info结构项的属性表、Code属性结构项Code_attributes的属性表中都有引用,这些属性表的每个元素均可以通过attribute_info结构项来描述,它项规定了所有属性的通用格式布局,具体如下:
Class文件格式(2)-深入理解ClassFile_第8张图片
        11.1.1、attribute_name_index
              u2类型的整数,指向常量池的有效索引,该索引处为CONSTANT_Utf8_info常量项,表示当前attribute_info所描述的属性的名称。
        11.1.2、attribute_length
              u4类型的整数,指明属性内容的字节长度,也即info[]数组所占用的字节数。
        11.1.3、info[attribute_lenght]
              存放属性内容的字节数组,数组长度有attribute_lenght指定。

    11.2、attributes[]

        属性可以是JVM预定义,也可以是程序在源代码中自定义的,JVMS7中指出了一些预定义的属性项,具体如下所示:
Class文件格式(2)-深入理解ClassFile_第9张图片
        这些预定义的属性项的结构以及其含义,后续会抽出专门的章节进行讲解,本文只对它们进行一些介绍性的说明。
        JVMS7还给出了这些预定义属性首次出现的JavaSE版本号和Class文件的版本号,具体如下:
Class文件格式(2)-深入理解ClassFile_第10张图片
       JVMS7规定
          Java虚拟机的Class文件加载器(class  file reader)必须能够正确读取ConstantVlaue、Code、Exceptions属性,同时JVM的实现能够正确的对这些属性进行解释。
          Java虚拟机的Class文件加载器必须识别并正确读取InnerClasses、EnclosingMethod、Synthetic属性,它们用于实现JavaSE平台的类库。
          如果JVM的实现能够识别版本号为49.0或者更高的Class文件,则该JVM的Class文件加载器必须能够从版本号为49.0或者更高的Class文件中识别并正确读取RuntimeVisibleAnnotations、 RuntimeInvisibleAnnotations、RuntimeVisibleParameterAnnotations、RuntimeInvisibleParameterAnnotations 、AnnotationDefault属性,这些属性用于实现JavaSE平台的类库。
          如果JVM的实现能够识别版本号为49.0或者更高的Class文件,则该JVM的Class文件加载器必须能够从版本号为49.0或者更高的Class文件中识别并正确读取Signature属性。 
          如果JVM的实现能够识别版本号为50.0或者更高的Class文件,则该JVM的Class文件加载器必须能够从版本号为50.0或者更高的Class文件中识别并正确读取StackMapTable属性。
          如果JVM的实现能够识别版本号为51.0或者更高的Class文件,则该JVM的Class文件加载器必须能够从版本号为51.0或者更高的Class文件中识别并正确读取BootstrapMethods属性。

你可能感兴趣的:(Java,&&,JVM)