zoukankan      html  css  js  c++  java
  • 6.7属性

    如前所述,属性在Java class文件中多处出现。它们可以出现在ClassFile、field_info、 method_info和Code_attribute表中。Code_attribme表本身即为一个属性,本节将对它进行阐述。(自我感悟:注意这里的field_info与后面的CONSTANT_Fieldref_info的区别,这里的field_info是指本类的field,而CONSTANT_Fieldref_info是指本类引用到的其他类的field,对于引用而言,因为CONSTANT_Fieldref_info只需描述被引用的field的名称和类型就可以了,而不需要包含被引用的field的access_flag,attributes等)

    如表6-24所示,Java虚拟机规范定义了9种属性。为了正确地解释java class文件,所有Java 虚拟机实现都必须能够识别下列三种属性:Code,Constant Value和Exception。为了正确地实现Java和Java 2平台类库,虚拟机实现必须能够识别InnerClasses和Synthetic属性,但可以自主选择 究竟是识别还是忽略其他一些预定义的属性(在Java 1.1中,加入了Deprecated、InnerClasses和 Synthetic属性(attribute))。所有这些预定义的属性将在本章详细阐述。
    表6-24由规范定义的attribute_info表的类型
    名称 使用者 描述
    Code method_info 方法的字节码和其他数据
    Constant_Value field_info final变量的值
    Deprccatcd ficld_info、method_info 宇段或者方法被禁用的指示符
    Exceptions method_info 方法可能抛出的可被检测的异常
    InnerClasses ClassFile 内部、外部类的列表
    LineNumbcrTable Code_attribute 方法的行号与字节码的映射
    LocalVariableTable Code_attribute 方法的局部变量的描述
    SourceFile ClassFile 源文件名
    Synthetic ficld_info、method_info 编译器产生的字段或者方法的指示符
    (自我感悟:注意上表的Code是指Code_attribute结构体的名称)
    表6-25 attribute_info表的格式
    类型 名 称 数量
    u2 attribute_name_index 1
    u4 attribute_length 1
    ul info attribute_length

    6.6 方法
    attributes_count 和 attributes
    attributes项是由多个attribute_info表组成的列表。attributes_count给出列表中attribute_info表的数量。一个字段在其列表中可以有任意数量的属性。在此项中可能会出现的由Java虚拟机规范 定义的四种属性是:Code、Deprecated、Exceptions和Synthetic。这四种属性将在本章后面进一步 阐述。Java虚拟机只需要识别Code和Exception属性。虚拟机实现必须忽略任何无法识别的属性。(自我感悟:注意这里的Exceptions与后面的code_attribute中的exception_table的区别,这里的Exceptions是指方法上声明的抛出的异常,而code_attribute中的exception_table是指code中的try-catch块中的异常信息)

    6.7.1属性格式

    如表6-25所示每一种属性都遵循同样的可变长度attribute_info表的一般格式。attribute_name_index属性的前两个字节构成了到C0NSTANT_Utf8_info表的常量池的索引,C0NSTANT_Utf8_info表中包含了属性的字符串名称。因此,每一个attribute_info表,由其表中的第1项指出了它的 “类型”,这种方式就像cp_info表中由初始tag字节指出它们的类型一样。不同的是,cp_info表的类型由一个无符号字节值指定,如3 ( CONSTANT_Integer_info ),而attribute_info表的类型由一个字符串指定。

    紧随attribute_name_index其后的是4字节长的attribute_length项,它给出除去起始6个字节后整个attribute_info表的长度(attribute_info项可以为0 )。因为只要遵循一定规则(如下所列)任何人都能够向Java class文件中加人属性,所以长度是不可缺少的。Java虚拟机实现能够识别新属性,实现必须忽略任何无法识别的属性。当解析class文件时,attribute_length允许虚拟机跳 过无法识别的属性。

    attribute_info表中各项如下所示:
    attribute_name_index

    attribute_name_index项给出了包含属性名称的CONSTANT_Utf8入口的常量池中的索引。
    attribute_length

    attribute_length项给出了属性数据的长度(以字节计),但是包括attribute_name_index和 attribute_length在内的起始6个字节不包括在内。

    info
    info项包含属性数据。

    6.7.2 Code属性

    可变长度的Code_attribute表定义了方法的字节码序列和其他信息。在所有不是抽象或者本地方法的method_info信息中,都存在一个Code_attribute表。Code_attribute表的格式如表6-26所示。

    表6-26 Code_attribute表的格式
    类型 名称 数量
    u2 attribute_name_index 1
    u4 attribute_length 1
    u2 max_stack 1
    u2 max_locals 1
    u4 code_length 1
    ul code code_length
    u2 exception_table_length 1
    exception_info exception_table exception_table_length
    u2 attributes_count 1
    attribute_info attributes attributes_count

    Code_attribute表中各项如下所示:
    attribute_name_index
    attribute_name_index项给出包含字符串“Code”的CONSTANT_utf8_info入口的常量池索引。

    attribute_length
    attribute_length项给出除去起始6个字节(包含attribute_name_index和attribute_length项)后, Code属性以字节为单位的长度。

    max_stack
    在方法执行中的任意时刻,max_stack项给出该方法的操作数栈的最大长度(以字为单位)。
    max_locals

    max_locals项给出方法的局部变量所需存储空间的长度(以字为单位)。无论虚拟机什么时候调用被Code属性所描述的方法,它都必须分配一个长度为max_locaIs的局部变量数组。这个数组用来存储传递给方法的参数以及为方法所使用的局部变量。long或者double类型值的最大有效 的局部变量索引是max_locals-2。任何其他类型值的最大有效局部变量索引为max_locals -1.(自我感言:该局部变量数组里存储的值要么是实际值,如基本类型的值,要么是引用类型的地址,如某个对象的地址)

    code_length 和 code

    code_length项给出该方法字节码流的长度(按字节计)。字节码本身将会出现在code项中。 code_length的值必须大于0。

    exception_table_length 和 exception_table

    exception_table项是一个exception_info表的列表。每个exception_info表都描述了一个异常表 项。exception_table_length项给出了exception_table中exception_info表的数目。exception_table 表在列表中按照方法执行抛出异常时Java虚拟机检查匹配异常处理器(catch子句)的顺序进行 排列。表exception_table的格式如表6-27所述,并在下面“exception__info表”部分进行阐述。如 果需要了解更多异常表的相关信息,请参照第17章。

    表6-27 exception_info表的格式
    类型 名称 数量
    u2 start_pc 1

    u2 end_pc 1

    u2 handler_pc 1

    u2 catch_type 1

    attributes_count 和 attributes

    attributes项是一个attribute_info表的列表。attributes_count项给出了列表中attribute_info表的数目。该项中可以出现Java虚拟机规范所定义的两种属性:LineNumberiable和 LocalVariableTable。这两种属性将在本章后面详细描述。Java虚拟机实现允许忽略Code属性内 attributes项中的任何属性,如果Java虚拟机无法识别这些属性,Java虚拟机必须忽略它们。

    exception_info 固定长度的exception_info表描述了一个异常表项。该表在Code属性中的 exception_info项中出现,它是exception_info表序列的组成部分。exception_info表的格式如表6-27所示。如果需要获取更多有关异常表的信息,请参照第17章。 exception_info表中各项如下所示:
    start_pc

    start_pc项给出从代码数组起始处到异常处理器起始处的偏移量。
    end_pc

    end_pc项给出从代码数组的起始处到异常处理器结束后一个字节的偏移量。
    handler_pc

    handler_pc项给出一条指令从代码数组起始处跳转到异常处理器的第1条指令的偏移量--如果抛出的异常被该项捕获的话。
    catch_iype

    catch_type项给出被该异常处理器所捕获的异常类型CONSTANT_class_info人口的常量池索引。CONSTANT_class_info入口必须描述了java.lang.Throwable类或其子类。

    如果catch_type的值为0 (不是一个有效的常量池索引,因为常量池从索引1开始),那么异 常处理器将处理所有的异常。一个值为0的catch_type用于实现finally子句。如果需要了解finally子句的实现。

    6.7.3 ConstantValue属性
    固定长度的ConstantValue属性出现在值为常量的字段的field_info表中。给定field_info表的 属性项中最多只可能出现一个ConstantValue属性。在包含ConstantValue属性的field_info表内的 access_flag中必须设定ACC_STATIC标志。尽管可能并不需要,但也可以设定ACC_FINAL标志。 当虚拟机初始化一个具有ConstantValue属性的字段时,它将一个常量值赋给这个字段。赋值操 作在虚拟机调用声明此字段的类或者接口的初始化方法之前进行。ConstantValue表的 格式如表6-28所示。


    表6-28 ConstantValue_attribute表的格式
    类型 名称 数量
    u2 attribute_name_index 1
    u4 attribute_length 1
    u2 constantvalue_index 1

    ConstantValue_attribute表中各项如下所示:
    attribute_name_index
    attribute_naine_index项给出包含字符串 “ConstantValue” 的CONSTANT_Utf8_info人口的常量池索引。

    attribute_length

    ConstantValue_attribute中的attribute_length项的值永远为 2。

    constantvalue_index

    constantvalue_index项给出提供常量值的人口的常量池索引。
    表6_29给出了对应于每一种字段类型的入口的类型。
    表6-29常量值属性的常量池入口类型
    常量值类型 常量池人口类型
    byte, short, char, int, boolean CONSTANT_Integer_info
    long CONSTANT_Long_info
    float CONSTANT_Float_info
    double CONSTANT_Double_info
    java.lang.String CONSTANT_String_info


    Deprecated_attribute表中各项如下所示:
    attribute_name_index

    attribute_name_index给出包含字符串 “Deprecated” 的CONSTANT_Utf8_info人口的常量池 索引。
    attribute_length 必须为0。

    6.7.5 Exceptions属性
    如果一个方法是RuntimeException、Error或者是在方法的Exceptions属性中所列出的异常的实例或子类,那么它应该只抛出一个异常。尽管这条规则应该被Java编译器强制执行,但它没有被Java虚拟机强制执行。因此,为了Java编译器,Exceptions属性存在于Java class文件中。

    number_of_exceptions 和 exception_index_table

    exception_index_table是一个该方法内throws子句中所声明异常的常量池中CONSTANT_Class_info入口的索引的数组。换句话说,exception_index_table列出了该方法可能抛出的所有已检出的异常。number_of_exceptions项指出了数组中索引的数目。

    6.7.7 LineNumberTable属性

    可变长度的LineNumberTable属性建立了方法字节码流偏移量和源代码行号之间的映射关系。LineNumberTable_attribute表可能会出现(可选)在Code_attribute表中的属性部分中。
    LineNumberTable_attribute 表的格式如表 6-35 所示。
    表6-35 LineNumberTable_attribute 表的格式
    类型 名称 数量
    u2 attribute_name_index 1
    u4 attribute_length 1
    u2 line_number_table_length 1
    line_number_info line_numbcr_table line_number_table_length

    LineNumberTable_attribute表中各项如下所示:

    attribute_name_index

    attribute_name_index给出包含字符串 “Line_Number_Table” 的CONSTANT_Utf8_info人口的常量池索引。
    attribute_length

    attribute_length给出除去起始6个字节(其中包含attribute_name_index和attribute_length项)后,LineNumberTable_attribute的长度(按字节计算)。 Line_number_table_length和line_number_table

    line_number_table项是一个成员为line_number_info表的数组。Line_number_table_length给出line_number_table数组中line_number_info表的数目。该数组中的表可以按照任何顺序排列, 该数组中也可能会有多个表对应一个行号的情况发生。line_number_info表的格式如表6-36所述。

    line_number_info表
    固定长度的line_number_info 表位于LineNumberTable_attribute表内的 line_number_table项中,它建立了源代码行号与字节码数组中的指令之间的联系,这里的字节码 数组对应于该行源代码的编译形式的开始位置。line_number_info表的格式如表6-36所示。

    line_number_info表中各项如下所示:
    start_pc

    start_pc给出了新行开始时代码数组的偏移量,该偏移量从代码数组的起始位置开始计算。 start_pc的值必须小于该LineNumberTable属性所属的Code属性中code_length项的值。
    line_number

    line_number项给出从start_pc开始的行号。

    6.7.8 LocalVariableTable属性

    可变长度的LocalVariable属性建立了方法的栈桢屮局部变量部分内容与源代码中局部变量的名称和描述符之间的映射关系。LocalVariableTable_attribute表可以(但不是一定)存在于 Code_auribute表的属性部分中。LocalVariableTable_attribute表的格式如表6-37所示。

    表6-37 LocalVariableTable_attribute表的格式

    类 型 名称 数量
    u2 attribute_name_index 1

    u4 attribute_length 1

    u2 local_variable_table_length 1

    local_variable_info local_variab_tab1e local_variable_table_length


    local_variable_info表 固定长度的表local_variable_info 位于 LocalVariableTable_attribute 表内 的local_variab_tab1e项中,它建立起源代码中局部变量的名称、类型与局部变量在字节码数组中的作用域、栈帧内局部变量中的索引之间的联系。local_variable_info表的格式如表6-38所示。

    表6-38 local_variable_info表的格式
    类型 名称 数 量
    U2 start_pc 1
    u2 length 1
    u2 name_index 1
    u2 descriptor_index 1
    u2 index 1


    local_variable_info表中各项如下所示:
    start_pc 和 length

    start_pc项给出代码数组中指令开始位置的偏移量。length项给出从start_pc开始的、所有局部变量有效的、代码的长度。位于从代码数组开始偏移量start_pc +length位置处的字节只能有下列两种情况:或者为一个指令的首字节,或者为代码数组结束后的首字节。
    name_index

    name_index项给出包含局部变量名称的CONSTANT_Utf8_info人口的常量池索引。 descriptor_index

    descriptor_index提供了CONSTANT_Utf8_info人口的索引,该人口提供了局部变量的描述符 (局部变量描述符符合与字段描述符相一致的语法)。
    index

    index项给出了在此方法栈帧中局部变量部分的索引,这是当方法执行时该局部变量数据所 保存的位置。如果局部变量的数据类型为long或者double,那么数据占据index和index +1位置的 两个字节;其他类型的变量数据占据index位置的一个字节。

    6.7.10 Synthetic 属性

    固定长度的Synthetic属性可能存在于field_info、method_info和ClassFile表内的attributes项 中,它是一个可选的项,它指明了为编译器所产生的字段、方法或者类型。未出现在源代码中 的类成员必须使用Synthetic属性标注。Synthetic属性在Java1.1版本中加人,用来提供对内嵌类 的支持。Synthetic_attribute表的格式如表6-40所示。

  • 相关阅读:
    简单查询
    Scott用户表
    记一次Sqoop抽数据异常
    Flink+Druid构建实时OLAP的探索
    客户端埋点实时OLAP指标计算方案
    Kafka服务不可用(宕机)问题踩坑记
    实时计算-多级订单金额,及下级人数
    Apache Druid0.15.0安装方式
    superset安装文档
    Scala的常用小技巧
  • 原文地址:https://www.cnblogs.com/mongotea/p/11979529.html
Copyright © 2011-2022 走看看