【JVM 规范】第四章

您所在的位置:网站首页 java常量定义格式 【JVM 规范】第四章

【JVM 规范】第四章

2023-01-01 17:22| 来源: 网络整理| 查看: 265

【JVM 规范】第四章-类文件结构-1

本文是 JVM19 规范的个人中文译本,原文为 docs.oracle.com/javase/spec…

本章描述了 Java 虚拟机的类文件格式。 每个类文件都包含单个类、接口或模块的定义。 尽管类、接口或模块不需要在文件中逐字包含外部表示(例如,因为类是由类加载器生成的),我们将通俗地引用类、接口或模块的任何有效表示 作为类文件格式。

类文件由 8 位字节流组成。 16 位和 32 位量分别通过读取两个和四个连续的 8 位字节来构造。 多字节数据项始终以大端顺序存储,其中高字节在前。 本章定义了数据类型 u1、u2 和 u4,分别表示无符号的 1、2 或 4 字节数量。

在 Java SE Platform API 中,类文件格式由接口 java.io.DataInput 和 java.io.DataOutput 以及 java.io.DataInputStream 和 java.io.DataOutputStream 等类支持。 例如,u1、u2、u4 类型的值可以通过接口 java.io.DataInput 的 readUnsignedByte、readUnsignedShort、readInt 等方法读取。

本章介绍使用类 C 结构符号编写的伪结构的类文件格式。 为了避免与类的字段和类实例等混淆,将描述类文件格式的结构内容称为项。 连续的元素按顺序存储在类文件中,没有填充或对齐。

表由零个或多个可变大小的元素组成,用于多个类文件结构。 尽管我们使用类似 C 的数组语法来引用表项,但表是不同大小结构的流这一事实意味着不可能将表索引直接转换为表中的字节偏移量。

我们将数据结构称为数组的地方,它由零个或多个连续的固定大小的元素组成,并且可以像数组一样进行索引。

本章中对 ASCII 字符的引用应解释为与 ASCII 字符对应的 Unicode 代码点。

4.1. 类文件结构

类文件由单个 ClassFile 结构组成:

ClassFile { u4 magic; u2 minor_version; u2 major_version; u2 constant_pool_count; cp_info constant_pool[constant_pool_count-1]; u2 access_flags; u2 this_class; u2 super_class; u2 interfaces_count; u2 interfaces[interfaces_count]; u2 fields_count; field_info fields[fields_count]; u2 methods_count; method_info methods[methods_count]; u2 attributes_count; attribute_info attributes[attributes_count]; } 复制代码

ClassFile 结构中的项如下:

magic 魔数项提供识别类文件格式的魔法数字; 它的值为 0xCAFEBABE。

minor_version major_version minor_version 和 major_version 项的值是此类文件的次要和主要版本号。 主要版本号和次要版本号共同决定类文件格式的版本。 如果一个类文件有主版本号 M 和次版本号 m,我们将其类文件格式的版本表示为 M.m。

符合 Java SE N 的 Java 虚拟机实现必须完全支持表 4.1-A 第四列“支持的主要版本”中指定的类文件格式的主要版本。 符号 A .. B 表示主要版本 A 到 B,包括 A 和 B。第三列“主要版本”显示每个 Java SE 版本引入的主要版本,即第一个可以接受的版本 包含该 major_version 项的类文件。 对于非常早的版本,显示的是 JDK 版本而不是 Java SE 版本。

Table 4.1-A. class file format major versions

Java SE 发布时间 主要版本 支持的主要版本 1.0.2 May 1996 45 45 1.1 February 1997 45 45 1.2 December 1998 46 45 .. 46 1.3 May 2000 47 45 .. 47 1.4 February 2002 48 45 .. 48 5.0 September 2004 49 45 .. 49 6 December 2006 50 45 .. 50 7 July 2011 51 45 .. 51 8 March 2014 52 45 .. 52 9 September 2017 53 45 .. 53

10

March 2018 54 45 .. 54

11

September 2018 55 45 .. 55

12

March 2019 56 45 .. 56

13

September 2019 57 45 .. 57

14

March 2020 58 45 .. 58

15

September 2020 59 45 .. 59

16

March 2021 60 45 .. 60

17

September 2021 61 45 .. 61

18

March 2022 62 45 .. 62

19

September 2022 63 45 .. 63

对于 major_version 为 56 或以上的 class 文件,minor_version 必须为 0 或 65535。

对于 major_version 介于 45 和 55 之间的类文件,minor_version 可以是任何值。

从历史的角度来看 JDK 对类文件格式版本的支持是有必要的。 JDK 1.0.2 支持版本 45.0 到 45.3(含)。 JDK 1.1 支持版本 45.0 到 45.65535(含)。 当 JDK 1.2 引入对主要版本 46 的支持时,该主要版本下唯一支持的次要版本是 0。后来的 JDK 继续引入对新主要版本(47、48 等)的支持但仅支持次要版本 0 的做法 在新的主要版本下。 最后,Java SE 12 中预览功能的引入(见下文)激发了小版本类文件格式的标准作用,因此 JDK 12 在大版本 56 下支持小版本 0 和 65535。后续的 JDK 引入了对 N 的支持 .0 和 N.65535,其中 N 是已实施 Java SE 平台的相应主要版本。 例如,JDK 13 支持 57.0 和 57.65535。

Java SE 平台可以定义预览特性。 符合 Java SE N(N ≥ 12)的 Java 虚拟机实现必须支持 Java SE N 的所有预览功能,并且不支持任何其他 Java SE 版本的预览功能。 实现必须默认禁用支持的预览功能,并且必须提供一种方法来启用所有这些功能,而不能提供一种方法来仅启用其中的一些功能。

如果一个类文件具有对应于 Java SE N(根据表 4.1-A)的 major_version 和 65535 的 minor_version,则称该类文件依赖于 Java SE N(N ≥ 12)的预览功能。

符合 Java SE N(N ≥ 12)的 Java 虚拟机实现必须表现如下:

依赖 Java SE N 预览特性的类文件只有在启用 Java SE N 预览特性的情况下才能被加载。 绝不能加载依赖于另一个 Java SE 版本的预览功能的类文件。 无论是否启用 Java SE N 的预览功能,都可以加载不依赖于任何 Java SE 版本的预览功能的类文件。

constant_pool_count

constant_pool_count 项的值等于 constant_pool 表中的条目数加一(常量池的中常量的个数实际是 constant_pool_count-1,译者注)。 如果 constant_pool 索引大于零且小于 constant_pool_count,则认为它是有效的,但 §4.4.5 中提到的 long 和 double 类型的常量除外。

constant_pool[]

constant_pool 是一个结构表 (§4.4),表示各种字符串常量、类和接口名称、字段名称以及在 ClassFile 结构及其子结构中引用的其他常量。 每个 constant_pool 表条目的格式由其第一个“tag”字节指示。

constant_pool 表的索引从 1 到 constant_pool_count - 1。

access_flags

access_flags 项的值是类访问标志的掩码,用于表示对此类或接口的访问权限和属性。 表 4.1-B 中规定了每个标志在设置时的解释。

Table 4.1-B. Class access and property modifiers

标志名称 值 解释 ACC_PUBLIC 0x0001 public声明 ACC_FINAL 0x0010 final声明 ACC_SUPER 0x0020 继承超类声明 ACC_INTERFACE 0x0200 接口声明 ACC_ABSTRACT 0x0400 抽象类声明 ACC_SYNTHETIC 0x1000 生成类声明 ACC_ANNOTATION 0x2000 注解类声明 ACC_ENUM 0x4000 枚举类声明

ACC_MODULE

0x8000 模块声明

ACC_MODULE 标志表示此类文件定义了一个模块,而不是类或接口。 如果设置了 ACC_MODULE 标志,则特殊规则适用于本节末尾给出的类文件。 如果未设置 ACC_MODULE 标志,则当前段落下方的规则适用于类文件。

接口通过设置 ACC_INTERFACE 标志来区分。 如果未设置 ACC_INTERFACE 标志,则此类文件定义一个类,而不是接口或模块。

如果设置了 ACC_INTERFACE 标志,则还必须设置 ACC_ABSTRACT 标志,并且不得设置 ACC_FINAL、ACC_SUPER、ACC_ENUM 和 ACC_MODULE 标志。

如果未设置 ACC_INTERFACE 标志,则可以设置表 4.1-B 中的任何其他标志,但 ACC_ANNOTATION 和 ACC_MODULE 除外。 但是,此类文件不能同时设置其 ACC_FINAL 和 ACC_ABSTRACT 标志(JLS §8.1.1.2)。

ACC_SUPER 标志指示如果 invokespecial 指令 (§invokespecial) 出现在此类或接口中,将表示两种可选语义中的哪一种。 Java 虚拟机指令集的编译器应该设置 ACC_SUPER 标志。 在 Java SE 8 及更高版本中,Java 虚拟机认为在每个类文件中都设置了 ACC_SUPER 标志,而不管类文件中标志的实际值和类文件的版本。

ACC_SUPER 标志的存在是为了向后兼容由旧编译器为 Java 编程语言编译的代码。 在 JDK 1.0.2 之前,编译器生成 access_flags,其中现在表示 ACC_SUPER 的标志没有指定的含义,如果设置了标志,Oracle 的 Java 虚拟机实现将忽略该标志。

ACC_SYNTHETIC 标志表示此类或接口是由编译器生成的,不会出现在源代码中。

注释接口 (JLS §9.6) 必须设置其 ACC_ANNOTATION 标志。 如果设置了 ACC_ANNOTATION 标志,则还必须设置 ACC_INTERFACE 标志。

ACC_ENUM 标志表示此类或其超类被声明为枚举类(JLS §8.9)。

未在表 4.1-B 中分配的 access_flags 项的所有位保留供将来使用。 它们应该在生成的类文件中设置为零,并且应该被 Java 虚拟机实现忽略。

this_class this_class 项的值必须是 constant_pool 表中的有效索引。 该索引处的 constant_pool 条目必须是 CONSTANT_Class_info 结构(第 4.4.1 节),表示此类文件定义的类或接口。

super_class 对于类,super_class 项的值必须为零或必须是 constant_pool 表中的有效索引。 如果 super_class 项的值不为零,则该索引处的 constant_pool 条目必须是 CONSTANT_Class_info 结构,表示此类文件定义的类的直接超类。 直接超类及其任何超类都不能在其 ClassFile 结构的 access_flags 项中设置 ACC_FINAL 标志。

如果 super_class 项的值为零,则此类文件必须代表类 Object,这是唯一没有直接超类的类或接口。

对于接口,super_class 项的值必须始终是 constant_pool 表中的有效索引。 该索引处的 constant_pool 条目必须是表示类 Object 的 CONSTANT_Class_info 结构。

interfaces_count interfaces_count 项的值给出了此类或接口类型的直接超接口的数量。

interfaces[] interfaces 数组中的每个值都必须是 constant_pool 表中的有效索引。 interfaces[i] 的每个值处的 constant_pool 条目,其中 0 ≤ i < interfaces_count,必须是一个 CONSTANT_Class_info 结构,表示一个接口,该接口是此类或接口类型的直接超接口,按照在中给出的从左到右的顺序 类型的来源。

fields_count fields_count 项的值给出了 fields 表中 field_info 结构的数量。 field_info 结构表示由此类或接口类型声明的所有字段,包括类变量和实例变量。

fields[] fields 表中的每个值都必须是一个 field_info 结构,给出此类或接口中字段的完整描述。 字段表仅包含此类或接口声明的那些字段。 它不包括表示从超类或超接口继承的字段的元素。

methods_count methods_count 项的值给出了 methods 表中 method_info 结构的数量。

methods[] methods 表中的每个值都必须是 method_info 结构,给出此类或接口中方法的完整描述。 如果在 method_info 结构的 access_flags 项中没有设置 ACC_NATIVE 和 ACC_ABSTRACT 标志,则还提供实现该方法的 Java 虚拟机指令。

method_info 结构表示此类或接口类型声明的所有方法,包括实例方法、类方法、实例初始化方法以及任何类或接口初始化方法。 方法表不包括表示从超类或超接口继承的方法的元素。

attributes_count attributes_count 项的值给出了该类的属性表中的属性数。

attributes[] 属性表的每个值都必须是一个 attribute_info 结构。

本规范定义的出现在 ClassFile 结构的属性表中的属性在表 4.7-C 中列出。

有关定义为出现在 ClassFile 结构的属性表中的属性的规则在 §4.7 中给出。

关于类文件结构的属性表中非预定义属性的规则在§4.7.1 中给出。

如果在 access_flags 项中设置了 ACC_MODULE 标志,则不能在 access_flags 项中设置其他标志,并且以下规则适用于 ClassFile 结构的其余部分:

major_version、minor_version:≥ 53.0(即 Java SE 9 及更高版本) this_class: 模块信息 super_class、interfaces_count、fields_count、methods_count:零 attributes:必须存在一个 Module 属性。 除了 Module、ModulePackages、ModuleMainClass、InnerClasses、SourceFile、SourceDebugExtension、RuntimeVisibleAnnotations 和 RuntimeInvisibleAnnotations 之外,预定义属性 (§4.7) 都不会出现。 4.2. 名称/名字规范 4.2.1. 二进制类/接口名

出现在类文件结构中的类和接口名称始终以称为二进制名称的完全限定形式表示 (JLS §13.1)。 此类名称始终表示为 CONSTANT_Utf8_info 结构(第 4.4.7 节),因此可以从整个 Unicode 代码空间中提取(不受进一步限制)。 类和接口名称是从那些 CONSTANT_NameAndType_info 结构中引用的,这些结构将这些名称作为其描述符的一部分,并且从所有 CONSTANT_Class_info 结构中引用。

由于历史原因,出现在类文件结构中的二进制名称的语法与 §13.1 中记录的二进制名称的语法不同。 在这种内部形式中,通常分隔构成二进制名称的标识符的 ASCII 句点 (.) 被 ASCII 正斜杠 (/) 替换。 标识符本身必须是非限定名称。

例如,类 Thread 的正常二进制名称是 java.lang.Thread。 在类文件格式的描述符中使用的内部形式中,对类 Thread 名称的引用是使用表示字符串 java/lang/Thread 的 CONSTANT_Utf8_info 结构实现的。

4.2.2. 不合格的名称

方法、字段、局部变量和形式参数的名称存储为非限定名称。 非限定名称必须至少包含一个 Unicode 代码点,并且不得包含任何 ASCII 字符 . ; [ /(即 句号、分号、左方括号、正斜杠)。

方法名称受到进一步限制,因此,除了特殊方法名称 和 (§2.9) 之外,它们不得包含 ASCII 字符 (即左尖括号或右尖括号) .

请注意,任何方法调用指令都不能引用 ,只有 invokespecial 指令 (§invokespecial) 可以引用 。

4.2.3. 模块和包名称

从 Module 属性引用的模块名称存储在常量池中的 CONSTANT_Module_info 结构中(§4.4.11)。 CONSTANT_Module_info 结构包装了一个表示模块名称的 CONSTANT_Utf8_info 结构。 模块名称不像类和接口名称那样以“内部形式”编码,也就是说,模块名称中分隔标识符的 ASCII 句点 (.) 不会被 ASCII 正斜杠 (/) 替换。

模块名称可以从整个 Unicode 代码空间中提取,但要遵守以下限制:

模块名称不得包含“\u0000”到“\u001F”范围内的任何代码点。 ASCII 反斜杠 (\) 保留用作模块名称中的转义字符。 它不能出现在模块名称中,除非它后跟 ASCII 反斜杠、ASCII 冒号 (:) 或 ASCII at 符号 (@)。 ASCII 字符序列 \\ 可用于对模块名称中的反斜杠进行编码。 ASCII 冒号 (:) 和 at 符号 (@) 保留供将来在模块名称中使用。 它们不能出现在模块名称中,除非它们被转义。 ASCII 字符序列 \: 和 \@ 可用于编码模块名称中的冒号和 at 符号。

从 Module 属性引用的包名称存储在常量池中的 CONSTANT_Package_info 结构中(§4.4.12)。 CONSTANT_Package_info 结构包装了一个 CONSTANT_Utf8_info 结构,该结构表示以内部形式编码的包名称。

4.3. 描述符

描述符是表示字段或方法类型的字符串。 描述符使用修改后的 UTF-8 字符串(第 4.4.7 节)以类文件格式表示,因此可以从整个 Unicode 代码空间中提取(不受进一步限制)。

4.3.1. 语法符号

描述符是使用语法指定的。 语法是一组描述字符序列如何形成语法正确的各种描述符的产生式。 语法的终端符号以固定宽度字体显示。 非终结符号以斜体显示。 非终结符的定义由被定义的非终结符的名称引入,后跟一个冒号。 非终结符的一个或多个替代定义随后在后续行中。 (译者注,下面的翻译可能不会按照上述规范进行字体的格式化,可以参考原文)

产生式右侧的语法 {x} 表示 x 出现零次或多次。 产生式右侧的短语 (one of) 表示接下来一行或几行中的每个终结符都是一个替代定义。 (译者注,这里的定义类似 BNF 定义)

4.3.2. 字段描述符

字段描述符表示类、实例或局部变量的类型。

FieldDescriptor: FieldType FieldType: BaseType ObjectType ArrayType BaseType: (one of) B C D F I J S Z ObjectType: L ClassName ; ArrayType: [ ComponentType ComponentType: FieldType 复制代码

BaseType 的字符,L 和; ObjectType 的 [ 和 ArrayType 的 [ 都是 ASCII 字符。

ClassName 表示以内部形式编码的二进制类或接口名称(§4.2.1)。

字段描述符作为类型的解释如表 4.3-A 所示。

表示数组类型的字段描述符仅当它表示具有 255 个或更少维度的类型时才有效。

Table 4.3-A. 字段描述符的解释

字段 term 类型 描述 B byte 有符号byte C char Unicode基本多平面的码点,使用UTF-16编码 D double 双精度浮点 F float 单精度浮点 I int 整数 J long 长整数 L ClassName ; reference 实例对象的类名 S short 有符号短整形 Z boolean true or false [ reference 数组

int 类型的实例变量的字段描述符就是简单的 I。

Object 类型的实例变量的字段描述符是 Ljava/lang/Object;。 请注意,使用了类 Object 的二进制名称的内部形式。

多维数组类型 double[][][] 的实例变量的字段描述符是 [[[D.

4.3.3. 方法描述符

方法描述符包含零个或多个参数描述符,表示方法采用的参数类型,以及返回描述符,表示方法返回值(如果有)的类型。

MethodDescriptor: ( {ParameterDescriptor} ) ReturnDescriptor ParameterDescriptor: FieldType ReturnDescriptor: FieldType VoidDescriptor VoidDescriptor: V 复制代码

字符 V 表示该方法不返回任何值(其结果为 void)。

方法的方法描述符:

Object m(int i, double d, Thread t) {...} -> (IDLjava/lang/Thread;)Ljava/lang/Object; 复制代码

请注意,使用了 Thread 和 Object 的二进制名称的内部形式。

方法描述符仅当它表示总长度为 255 或更短的方法参数时才有效,其中该长度包括在实例或接口方法调用的情况下对此的贡献。 总长度是通过对各个参数的贡献求和来计算的,其中 long 或 double 类型的参数对长度贡献两个单位,任何其他类型的参数贡献一个单位。

无论它描述的方法是类方法还是实例方法,方法描述符都是相同的。 尽管向实例方法传递了 this,即对调用该方法的对象的引用,以及其预期的参数,但该事实并未反映在方法描述符中。 对 this 的引用由调用实例方法的 Java 虚拟机指令隐式传递(§2.6.1,§4.11)。

4.4. 常量池

Java 虚拟机指令不依赖于类、接口、类实例或数组的运行时布局。 相反,指令引用 constant_pool 表中的符号信息。

所有 constant_pool 表条目都具有以下通用格式:

cp_info { u1 tag; u1 info[]; } 复制代码

constant_pool 表中的每个条目都必须以一个 1 字节的标记开头,该标记指示该条目表示的常量类型。 常量共有 17 种,在表 4.4-A 中列出了它们对应的标签,并按它们在本章中的章节编号排序。 每个标记字节后面必须跟两个或更多字节,提供有关特定常量的信息。 附加信息的格式取决于 tag 字节,即 info 数组的内容随着 tag 的值而变化。

Table 4.4-A. 常量池字节标志

常量类型 标志 CONSTANT_Class 7 CONSTANT_Fieldref 9 CONSTANT_Methodref 10 CONSTANT_InterfaceMethodref 11 CONSTANT_String 8 CONSTANT_Integer 3 CONSTANT_Float 4 CONSTANT_Long 5 CONSTANT_Double 6 CONSTANT_NameAndType 12 CONSTANT_Utf8 1 CONSTANT_MethodHandle 15 CONSTANT_MethodType 16 CONSTANT_Dynamic 17 CONSTANT_InvokeDynamic 18 CONSTANT_Module 19 CONSTANT_Package 20

在版本号为 v 的类文件中,constant_pool 表中的每个条目都必须有一个标记,该标记首先在版本 v 或更早的类文件格式(§4.1)中定义。 也就是说,每个条目必须表示一种批准在类文件中使用的常量。 表 4.4-B 列出了每个标签以及定义它的类文件格式的第一个版本。 还显示了引入该类文件格式版本的 Java SE 平台版本。

Table 4.4-B. Constant pool tags (by tag)

常量类型 标志 class file format Java SE CONSTANT_Utf8 1 45.3 1.0.2 CONSTANT_Integer 3 45.3 1.0.2 CONSTANT_Float 4 45.3 1.0.2 CONSTANT_Long 5 45.3 1.0.2 CONSTANT_Double 6 45.3 1.0.2 CONSTANT_Class 7 45.3 1.0.2 CONSTANT_String 8 45.3 1.0.2 CONSTANT_Fieldref 9 45.3 1.0.2 CONSTANT_Methodref 10 45.3 1.0.2 CONSTANT_InterfaceMethodref 11 45.3 1.0.2 CONSTANT_NameAndType 12 45.3 1.0.2 CONSTANT_MethodHandle 15 51.0 7 CONSTANT_MethodType 16 51.0 7 CONSTANT_Dynamic 17 55.0 11 CONSTANT_InvokeDynamic 18 51.0 7 CONSTANT_Module 19 53.0 9 CONSTANT_Package 20 53.0 9

constant_pool 表中的一些条目是可加载的,因为它们代表可以在运行时被压入堆栈以启用进一步计算的实体。 在版本号为 v 的类文件中,如果 constant_pool 表中的条目具有在类文件格式的版本 v 或更早版本中首先被认为可加载的标记,则该条目是可加载的。 表 4.4-C 列出了每个标签以及被认为可加载的类文件格式的第一个版本。 还显示了引入该类文件格式版本的 Java SE 平台版本。

在除 CONSTANT_Class 之外的所有情况下,标签首先被认为可以加载到与首先定义该标签的类文件格式相同的版本中。

Table 4.4-C. Loadable constant pool tags

常量类型 标志 class file format Java SE CONSTANT_Integer 3 45.3 1.0.2 CONSTANT_Float 4 45.3 1.0.2 CONSTANT_Long 5 45.3 1.0.2 CONSTANT_Double 6 45.3 1.0.2 CONSTANT_Class 7 49.0 5.0 CONSTANT_String 8 45.3 1.0.2 CONSTANT_MethodHandle 15 51.0 7 CONSTANT_MethodType 16 51.0 7 CONSTANT_Dynamic 17 55.0 11 4.4.1. CONSTANT_Class_info 结构

CONSTANT_Class_info 结构用于表示类或接口:

CONSTANT_Class_info { u1 tag; u2 name_index; } 复制代码

CONSTANT_Class_info 结构体的各项如下:

tag 标记项的值为 CONSTANT_Class (7)。 name_index name_index 项的值必须是 constant_pool 表中的有效索引。 该索引处的 constant_pool 条目必须是 CONSTANT_Utf8_info 结构(§4.4.7),表示以内部形式(§4.2.1)编码的有效二进制类或接口名称。

因为数组是对象,所以操作码 anewarray 和 multianewarray - 但不是操作码 new - 可以通过 constant_pool 表中的 CONSTANT_Class_info 结构引用数组“类”。 对于此类数组类,类的名称是数组类型的描述符(§4.3.2)。

例如表示二维数组类型int[][]的类名是[[I,而表示Thread[]类型的类名是[Ljava/lang/Thread;。

数组类型描述符只有在表示 255 个或更少的维度时才有效。

4.4.2. CONSTANT_Fieldref_info、CONSTANT_Methodref_info 和 CONSTANT_InterfaceMethodref_info 结构

字段、方法和接口方法用类似的结构表示:

CONSTANT_Fieldref_info { u1 tag; u2 class_index; u2 name_and_type_index; } CONSTANT_Methodref_info { u1 tag; u2 class_index; u2 name_and_type_index; } CONSTANT_InterfaceMethodref_info { u1 tag; u2 class_index; u2 name_and_type_index; } 复制代码

这些结构的元素如下:

tag

CONSTANT_Fieldref_info 结构的标记项的值为 CONSTANT_Fieldref (9) CONSTANT_Methodref_info 结构的标记项的值为 CONSTANT_Methodref (10)。 CONSTANT_InterfaceMethodref_info 结构的标记项的值为 CONSTANT_InterfaceMethodref (11)。

class_index

class_index 项的值必须是 constant_pool 表中的有效索引。 该索引处的 constant_pool 条目必须是 CONSTANT_Class_info 结构(第 4.4.1 节),表示具有字段或方法作为成员的类或接口类型。 在 CONSTANT_Fieldref_info 结构中,class_index 项可以是类类型或接口类型。 在 CONSTANT_Methodref_info 结构中,class_index 项应该是类类型,而不是接口类型。 在 CONSTANT_InterfaceMethodref_info 结构中,class_index 项应该是接口类型,而不是类类型。

name_and_type_index

name_and_type_index 项的值必须是 constant_pool 表中的有效索引。 该索引处的 constant_pool 条目必须是 CONSTANT_NameAndType_info 结构(§4.4.6)。 此 constant_pool 条目指示字段或方法的名称和描述符。 在 CONSTANT_Fieldref_info 结构中,指示的描述符必须是字段描述符(§4.3.2)。 否则,指示的描述符必须是方法描述符(§4.3.3)。 如果 CONSTANT_Methodref_info 结构中的方法名称以“> 31) == 0) ? 1 : -1; int e = ((bits >> 23) & 0xff); int m = (e == 0) ? (bits & 0x7fffff) > 52) & 0x7ffL); long m = (e == 0) ? (bits & 0xfffffffffffffL)


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3