JVM类文件结构
本文最后更新于 2025年9月10日 下午
结构
Class 文件是一组以8个字节为基础的二进制流,各个数据项目严格按照顺序紧凑地排列在文件之中,中间没有添加任何分隔符,这使得整个文件中存储的内容几乎全部是程序运行的必要数据,没有空隙存在。这种结构中主要使用了两种数据类型
无符号数 :
无符号数属于基本数据类型,以u1,u2,u4,u8来分别代表1个字节,2个字节,4个字节和8个字节的无符号数,可以用来描述数字,索引引用,数量值或者以UT8-8编码构成的字符串
表:
表是由多个无符号数或者其他表作为数据项构成的复合数据类型,为了便于区分,所有表的命名都可以习惯性地以“_info”结尾,表用于描述有层次关系的复合结构的数据。
无论是无符号数还是表,当需要描述同意类型但数量不定的多个数据时,会使用一个前置的容量计数器家若干个连续的数据项的形式,这种时候称这一系列的某一类型的数据为某一类型的“集合”

魔数(4字节)
用于确定一个文件是否为一个能被虚拟机接收的Class文件。
版本号信息
(2字节 + 2字节) 次版本号和主版本号
常量池计数(2字节)
1 | |
常量池 (集合)
常量池中包含两大类常量,字面量和符号引用
主要包括 :
- 被模块导出或者开放的包
- 类和接口的全限定名
- 字段的名称和描述符
- 方法句柄和方法类型
- 动态调用点和动态常量
常量池中的项目结构
| 类型 | 标志 | 描述 |
|---|---|---|
| CONSTANT_Utf8_info | 1 | UTF-8编码的字符串 |
| CONSTANT_Integer_info | 3 | 整型字面量 |
| CONSTANT_Float_info | 4 | 浮点型字面量 |
| CONSTANT_Long_info | 5 | 长整型字面量 |
| CONSTANT_Double_info | 6 | 双精度浮点型字面量 |
| CONSTANT_Class_info | 7 | 类或接口的符号引用 |
| CONSTANT_String_info | 8 | 字符串类型字面量 |
| CONSTANT_Fildref_info | 9 | 字段的符号引用 |
| CONSTANT_Methodref_info | 10 | 类中方法的符号引用 |
| CONSTANT_InterfaceMethodref_info | 11 | 接口中方法的符号引用 |
| CONSTANT_NameAndType_info | 12 | 字段或方法的部分符号引用 |
| CONSTANT_MethodHandle_info | 15 | 表示方法句柄 |
| CONSTANT_MethodType_info | 16 | 表示方法类型 |
| CONSTANT_Dynamic_info | 17 | 表示一个动态计算常量 |
| CONSTANT_InvokeDynamic_info | 18 | 表示一个动态方法调用点 |
| CONSTANT_Module_info | 19 | 表示一个模块 |
| CONSTANT_Package_info | 20 | 表示一个模块中开放或者导出的包 |
CONSTANT_Class_info
| 类型 | 名称 | 数量 |
|---|---|---|
| u1 | tag | 1 |
| u2 | name_index | 1 |
说明: tag=7。用于表示类或接口的符号引用。name_index指向常量池中一个CONSTANT_Utf8_info类型的常量,该常量存储了这个类或接口的全限定名(如java/lang/String)。全限定名使用”/“分隔包名,而不是”.”。
CONSTANT_Fieldref_info
| 类型 | 名称 | 数量 |
|---|---|---|
| u1 | tag | 1 |
| u2 | class_index | 1 |
| u2 | name_and_type_index | 1 |
说明: tag=9。用于表示字段的符号引用。class_index指向CONSTANT_Class_info类型常量,表示该字段所属的类或接口;name_and_type_index指向CONSTANT_NameAndType_info类型常量,表示该字段的简单名称和字段描述符。字段描述符用于描述字段的数据类型。
CONSTANT_Methodref_info
| 类型 | 名称 | 数量 |
|---|---|---|
| u1 | tag | 1 |
| u2 | class_index | 1 |
| u2 | name_and_type_index | 1 |
说明: tag=10。用于表示类中方法的符号引用。class_index指向CONSTANT_Class_info类型常量,表示该方法所属的类;name_and_type_index指向CONSTANT_NameAndType_info类型常量,表示该方法的简单名称和方法描述符。方法描述符描述了方法的参数类型列表和返回值类型。
CONSTANT_InterfaceMethodref_info
| 类型 | 名称 | 数量 |
|---|---|---|
| u1 | tag | 1 |
| u2 | class_index | 1 |
| u2 | name_and_type_index | 1 |
说明: tag=11。用于表示接口中方法的符号引用。class_index必须指向CONSTANT_Class_info类型常量,且该常量必须表示一个接口而非类;name_and_type_index指向CONSTANT_NameAndType_info类型常量,表示该接口方法的简单名称和方法描述符。
CONSTANT_String_info
| 类型 | 名称 | 数量 |
|---|---|---|
| u1 | tag | 1 |
| u2 | string_index | 1 |
说明: tag=8。用于表示String类型的常量对象。string_index指向CONSTANT_Utf8_info类型常量,该常量存储了String对象的值。这种常量用于支持Java源码中的字符串字面量,如”Hello World”。
CONSTANT_Integer_info
| 类型 | 名称 | 数量 |
|---|---|---|
| u1 | tag | 1 |
| u4 | bytes | 1 |
说明: tag=3。用于表示int类型的常量值。bytes字段按照高位在前(Big-Endian)的顺序存储32位有符号整数。这种常量用于支持Java源码中的int类型字面量和final修饰的int类型字段的初始值。
CONSTANT_Float_info
| 类型 | 名称 | 数量 |
|---|---|---|
| u1 | tag | 1 |
| u4 | bytes | 1 |
说明: tag=4。用于表示float类型的常量值。bytes字段按照IEEE 754单精度浮点数格式存储,采用高位在前的字节序。用于支持Java源码中的float类型字面量和final修饰的float类型字段的初始值。
CONSTANT_Long_info
| 类型 | 名称 | 数量 |
|---|---|---|
| u1 | tag | 1 |
| u4 | high_bytes | 1 |
| u4 | low_bytes | 1 |
说明: tag=5。用于表示long类型的常量值。由high_bytes和low_bytes两个字段组成64位有符号长整数,按照高位在前的顺序存储。该常量占用常量池中的两个连续索引位置,第二个索引位置被认为是无效的。
CONSTANT_Double_info
| 类型 | 名称 | 数量 |
|---|---|---|
| u1 | tag | 1 |
| u4 | high_bytes | 1 |
| u4 | low_bytes | 1 |
说明: tag=6。用于表示double类型的常量值。按照IEEE 754双精度浮点数格式存储,由high_bytes和low_bytes组成64位浮点数,采用高位在前的字节序。与long类型常量一样,占用常量池中的两个连续索引位置。
CONSTANT_NameAndType_info
| 类型 | 名称 | 数量 |
|---|---|---|
| u1 | tag | 1 |
| u2 | name_index | 1 |
| u2 | descriptor_index | 1 |
说明: tag=12。用于表示字段或方法的部分符号引用。name_index指向CONSTANT_Utf8_info类型常量,存储字段或方法的简单名称(不包含类名);descriptor_index指向CONSTANT_Utf8_info类型常量,存储字段的字段描述符或方法的方法描述符。描述符用规范化的字符串描述数据类型。
CONSTANT_Utf8_info
| 类型 | 名称 | 数量 |
|---|---|---|
| u1 | tag | 1 |
| u2 | length | 1 |
| u1 | bytes | length |
说明: tag=1。用于表示UTF-8编码的字符串常量,是常量池中最基础的常量类型。length字段表示后续字节数组的长度(注意不是字符个数);bytes字段存储使用UTF-8缩略编码的字符串内容。由于length是u2类型,所以单个字符串的最大字节长度为65535字节。几乎所有其他常量类型都会引用此类型来存储文本信息。
CONSTANT_MethodHandle_info
| 类型 | 名称 | 数量 |
|---|---|---|
| u1 | tag | 1 |
| u1 | reference_kind | 1 |
| u2 | reference_index | 1 |
说明: tag=15。用于表示方法句柄常量,支持Java 7引入的invokedynamic指令和方法句柄机制。reference_kind字段表示方法句柄的种类(1-9对应不同的操作类型,如getField、putField、invokeVirtual等);reference_index根据reference_kind的值指向常量池中相应的字段引用、方法引用或接口方法引用常量。
CONSTANT_MethodType_info
| 类型 | 名称 | 数量 |
|---|---|---|
| u1 | tag | 1 |
| u2 | descriptor_index | 1 |
说明: tag=16。用于表示方法类型常量,支持Java 7的invokedynamic指令。descriptor_index指向CONSTANT_Utf8_info类型常量,该常量存储方法描述符,描述了方法的参数类型列表和返回值类型,但不包含方法名。方法类型常量用于在运行时表示方法的签名信息。
CONSTANT_Dynamic_info
| 类型 | 名称 | 数量 |
|---|---|---|
| u1 | tag | 1 |
| u2 | bootstrap_method_attr_index | 1 |
| u2 | name_and_type_index | 1 |
说明: tag=17。用于表示动态计算常量,支持Java 11引入的动态常量特性。bootstrap_method_attr_index指向类文件属性表中BootstrapMethods属性的bootstrap_methods数组的索引,该引导方法在运行时负责计算常量的值;name_and_type_index指向CONSTANT_NameAndType_info类型常量,描述动态常量的名称和类型描述符。
CONSTANT_InvokeDynamic_info
| 类型 | 名称 | 数量 |
|---|---|---|
| u1 | tag | 1 |
| u2 | bootstrap_method_attr_index | 1 |
| u2 | name_and_type_index | 1 |
说明: tag=18。用于表示invokedynamic指令要调用的动态方法,支持Java 7引入的invokedynamic特性。bootstrap_method_attr_index指向BootstrapMethods属性中引导方法的索引,该引导方法在首次执行时负责解析调用点并返回CallSite对象;name_and_type_index指向CONSTANT_NameAndType_info类型常量,描述动态方法调用的方法名和方法描述符。
CONSTANT_Module_info
| 类型 | 名称 | 数量 |
|---|---|---|
| u1 | tag | 1 |
| u2 | name_index | 1 |
说明: tag=19。用于表示模块的符号引用,支持Java 9引入的模块系统。name_index指向CONSTANT_Utf8_info类型常量,该常量存储模块的名称(如java.base)。这种常量主要用于module-info.class文件中,描述模块的依赖关系、导出包等模块元数据。
CONSTANT_Package_info
| 类型 | 名称 | 数量 |
|---|---|---|
| u1 | tag | 1 |
| u2 | name_index | 1 |
说明: tag=20。用于表示包的符号引用,支持Java 9的模块系统。name_index指向CONSTANT_Utf8_info类型常量,该常量存储包的名称(如java/lang,使用”/“分隔)。这种常量主要用于module-info.class文件中,用于描述模块导出的包、打开的包等信息。
访问标志
访问标志用于识别一些类或者接口层次的访问信息,包括这个Class 是类还是接口;是否定义为public类型;是否定义为abstract类型;如果是类的话是否被声明为final
| 标志名称 | 标志值 | 含义 |
|---|---|---|
| ACC_PUBLIC | 0x0001 | 是否为public类型 |
| ACC_FINAL | 0x0010 | 是否被声明为final |
| ACC_SUPER | 0x0020 | 是否使用invokespecial字节码指令的新语义 |
| ACC_INTERFACE | 0x0200 | 标识这是一个接口 |
| ACC_ABSTRACT | 0x0400 | 是否为抽象类型 |
| ACC_SYNTHETIC | 0x1000 | 标识这个类并非由用户代码产生的 |
| ACC_ANNOTATION | 0x2000 | 标识这是一个注解 |
| ACC_ENUM | 0x4000 | 标识这是一个枚举 |
| ACC_MODULE | 0x8000 | 标识这是一个模块 |
类索引
用于确定这个类的全限定名
父类索引
用于确定这个类的父类的全限定名,而除了Object外,所有类的父类索引都不为0
接口索引集合
用于描述这个类实现了哪些接口,这些被实现的接口将按implements关键字后的接口顺序从左到右排列在接口索引集合中。
接口索引计数器
如果为0 则该类未实现任何接口,则接口索引集合不占用任何字节
字段表集合
字段表(field_info)用于描述接口或者类中声明的变量,Java语言中的“字段”包括类级变量以及实例级变量,但不包括在方法内部声明的局部变量。上述信息中,每个修饰符都是布尔值。
| 类型 | 名称 | 数量 |
|---|---|---|
| u2 | access_flags | 1 |
| u2 | name_index | 1 |
| u2 | descriptor | 1 |
| u2 | attributes_count | 1 |
| attribute_info | attributes | attributes_counter |
字段访问标志
| 标志名称 | 标志值 | 含义 |
|---|---|---|
| ACC_PUBLIC | 0x0001 | 字段是否public |
| ACC_PRIVATE | 0x0002 | 字段是否private |
| ACC_PROTECTED | 0x0004 | 字段是否protected |
| ACC_STATIC | 0x0008 | 字段是否static |
| ACC_FINAL | 0x0010 | 字段是否final |
| ACC_VOLATILE | 0x0040 | 字段是否volatile |
| ACC_TRANSIENT | 0x0080 | 字段是否transient |
| ACC_SYNTHETIC | 0x0010 | 字段是否由编译器自动产生 |
| ACC_ENUM | 0x4000 | 字段是否enum |
简单名称,描述符和全限定名
简单名称: 没有类型和参数修饰的方法或者字段名称
全限定名:具有包路径的全部类名称使用”/”连接
描述符:描述字段的数据类型,方法的参数列表和返回值
| 标识字符 | 含义 |
|---|---|
| B | 基本类型byte |
| C | 基本类型char |
| D | 基本类型double |
| F | 基本类型float |
| I | 基本类型int |
| J | 基本类型long |
| S | 基本类型short |
| Z | 基本类型boolean |
| V | 特殊类型void |
| L | 对象类型 |
对于数组类型,每一维度将使用一个前置的“[”字符来描述,多维数组则继续向前面添加”[” 。
方法则被描述为()。
属性表
有时候会在后续存在一个属性表信息
方法表集合
| 类型 | 名称 | 数量 |
|---|---|---|
| u2 | access_flags | 1 |
| u2 | name_index | 1 |
| u2 | descriptor_index | 1 |
| u2 | attributes_count | 1 |
| attribute_info | attributes | attribute_count |
字段访问标志
| 标志名称 | 标志值 | 含义 |
|---|---|---|
| ACC_PUBLIC | 0x0001 | 方法是否为public |
| ACC_PRIVATE | 0x0002 | 方法是否为private |
| ACC_PROTECTED | 0x0004 | 方法是否为protected |
| ACC_STATIC | 0x0008 | 方法是否为static |
| ACC_FINAL | 0x0010 | 方法是否为final |
| ACC_SYNCHRONIZED | 0x0020 | 方法是否为synchronized |
| ACC_BRIDGE | 0x0040 | 方法是不是由编译器产生的桥接方法 |
| ACC_VARRGS | 0x0080 | 方法是否接受不定参数 |
| ACC_NATIVE | 0x0100 | 方法是否为native |
| ACC_ABSTRACT | 0x0400 | 方法是否为abstract |
| ACC_STRICT | 0x0800 | 方法是否为strictfp |
| ACC_SYNTHETIC | 0x1000 | 方法是否由编译器自动产生 |
方法的执行代码被存储在属性表集合的Code属性里面
| 属性名称 | 使用位置 | 含义 |
|---|---|---|
| Code | 方法表 | Java代码编译成的字节码指令 |
| ConstantValue | 字段表 | final关键字定义的常量值 |
| Deprecated | 类、方法表、字段表 | 被声明为deprecated的方法和字段 |
| Exceptions | 方法表 | 方法抛出的异常 |
| InnerClasses | 类文件 | 记录内部类与宿主类之间的关联 |
| LineNumberTable | Code属性 | Java源码行号与字节码指令的对应关系 |
| LocalVariableTable | Code属性 | 方法的局部变量描述 |
| SourceFile | 类文件 | 记录源文件名称 |
| Synthetic | 类、方法表、字段表 | 标识方法或字段为编译器自动生成的 |
| StackMapTable | Code属性 | 用于新的类型检查验证器验证和处理目标方法的局部变量和操作数栈所需要的类型是否匹配 |
| Signature | 类、方法表、字段表 | 可选的定长属性,它可以出现于类、属性表和方法表结构的属性表中 |
| BootstrapMethods | 类文件 | 用于保存invokedynamic指令引用的引导方法限定符 |
| MethodParameters | 方法表 | 用于支持(编译时加上-parameters参数)将方法名称编译进Class文件中,并可运行时获取 |
| RuntimeVisibleAnnotations | 类、方法表、字段表 | 为动态注解提供支持,用于指明哪些注解是运行时可见的 |
| RuntimeInvisibleAnnotations | 类、方法表、字段表 | 与RuntimeVisibleAnnotations相反,用于指明哪些注解是运行时不可见的 |
| RuntimeVisibleParameterAnnotations | 方法表 | 作用与RuntimeVisibleAnnotations类似,只不过作用对象为方法参数 |
| RuntimeInvisibleParameterAnnotations | 方法表 | 作用与RuntimeInvisibleAnnotations类似,只不过作用对象为方法参数 |
| AnnotationDefault | 方法表 | 用于记录注解类元素的默认值 |
| LocalVariableTypeTable | Code属性 | 它使用特征签名代替描述符,是为了引入泛型语法之后能描述泛型参数化类型而添加 |
| EnclosingMethod | 类文件 | 当一个类为局部类或者匿名类时,才能拥有这个属性,这个属性用于标示这个类所在的外围方法 |
| Module | 类 | JDK9中新增属性,用于记录一个Module的名称以及相关信息 |
| ModulePackages | 类 | JDK9中新增属性,用于记录一个模块中所有被exports或者opens的包 |
| ModuleMainClass | 类 | JDK9中新增属性,用于指定一个模块的主类 |
| NestHost | 类 | JDK11中新增属性,用于支持嵌套类的反射和访问控制的API,一个内部类通过该属性得知自己的宿主类 |
| NestMembers | 类 | JDK11中新增属性,用于支持嵌套类的反射和访问控制的API,一个宿主类通过该属性得知自己有哪些内部类 |
| SourceDebugExtension | 类文件 | 用于存储额外的调试信息 |
| RuntimeVisibleTypeAnnotations | 类,方法表,字段表,Code属性 | JDK8中新增属性,用于指明哪些类注解是运行时可见的 |
| RuntimeInvisibleTypeAnnotations | 类,方法表,字段表,Code属性 | JDK8中新增属性,用于指明哪些类注解是运行时不可见的 |
属性表结构
| 类型 | 名称 | 数量 |
|---|---|---|
| u2 | attribute_name_index | 1 |
| u4 | attribute_length | 1 |
| u1 | info | attribute_length |
Code属性
| 类型 | 名称 | 数量 |
|---|---|---|
| u2 | attribute_name_index | 1 |
| u4 | attribute_length | 1 |
| u2 | max_stack | 1 |
| u2 | max_locals | 1 |
| u4 | code_length | 1 |
| u1 | code | code_length |
| u2 | exception_table_length | 1 |
| exception_info | exception_table | exception_table_length |
| u2 | attributes_count | 1 |
| attribute_info | attributes | attributes_count |
attribute_name_index 是一项指向CONSTANT_Utf8_info型常量的索引,此常量值固定为“Code”,它代表了该属性的属性名称
attribute_length指示了属性值的长度,由于属性名称索引与属性长度一共为6个字节,所以属性值长度固定为属性表长度-6
max_stack 代表了操作数栈深度的最大值,在方法执行的任意时刻,操作数栈都不会超过这个深度。虚拟机运行的时候要根据这个值来分配栈帧中的操作栈深度
max_locals 代表了局部变量表所需的存储空间,单位是变量槽。代码执行超出一个局部变量的作用域时,这个局部变量所占的变量槽可以被其他局部变量所使用。编译器会根据变量的作用域来分配变量槽给各个变量使用,根据同时生存的最大局部变量数量和类型计算出max_locals
code_length 和 code 用来存储Java源程序编译后生成的字节码指令。code_length代表字节码长度,code是用于存储字节码指令的一系列字节流。
字节码指令是 u1类型的单字节控制字符, u1的取值范围在0-255
code_length 中 定义了u4类型的长度,但实际上只是用u2长度
Code属性是用于描述具体的代码,
异常表集合
异常表对于Code属性来说并不是必须存在的
| 类型 | 名称 | 数量 |
|---|---|---|
| u2 | start_pc | 1 |
| u2 | end_pc | 1 |
| u2 | handler_pc | 1 |
| u2 | catch_type | 1 |
Exceptions属性
Exceptions属性是在方法表中与Code属性平级的一项属性,列举方法中可能抛出的受查异常。
| 类型 | 名称 | 数量 |
|---|---|---|
| u2 | attribute_name_index | 1 |
| u4 | attribute_length | 1 |
| u2 | number_of_exceptions | 1 |
| u2 | exception_index_table | number_of_exceptions |
number_of_exceptions 表示方法可能抛出number_of_exceptions 种受查异常
每一种受查异常用一个exception_index_table项表示
exception_index_table 是一个指向常量池中CONSTANT_Class_info型常量的索引。代表了该受查异常的类型
LineNumberTable 属性
| 类型 | 名称 | 数量 |
|---|---|---|
| u2 | attribute_name_index | 1 |
| u4 | attribute_length | 1 |
| u2 | line_number_table_length | 1 |
| line_number_info | line_number_table | line_number_table_length |
LineNumberTable 属性用于描述Java源行号与字节码行号之间的对应关系。
line_number_table 是一个数量为line_number_table_length,类型为line_number_info的集合,line_number_info表包含start_pc, 和 line_number 两个u2类型的数据项,前者是字节码行号,后者是java源码行号
LocalVariableTable和LocalVariableTypeTable属性
LocalVariableTable 属性用于描述栈帧中局部变量表的变量与Java源码中定义的变量之间的关系。
| 类型 | 名称 | 数量 |
|---|---|---|
| u2 | attribute_name_index | 1 |
| u4 | attribute_length | 1 |
| u2 | local_variable_table_length | 1 |
| local_variable_info | local_variable_table | local_variable_table_length |
local_variable_info 项目代表了一个栈帧与源码中的局部变量的关联
| 类型 | 名称 | 数量 |
|---|---|---|
| u2 | start_pc | 1 |
| u2 | length | 1 |
| u2 | name_index | 1 |
| u2 | descriptor_index | 1 |
| u2 | index | 1 |
start_pc 和 length 属性分别代表了这个局部变量的生命周期开始的字节码偏移量及其作用范围覆盖的长度,两者结合就是这个局部变量在字节码之中的作用域范围
name_index 和 descriptor_index 都是指向常量池中CONSTANT_Utf8_info型常量的索引,分别代表了局部变量的名称以及整个局部变量的描述符
index 是整个局部变量在栈帧的局部变量表中变量操的位置。当这个变量数据类型是64位类型时,它占用的变量槽位位index和index+1
SourceFile 及SourceDebugExtension属性
SourceFile用于记录生成这个Class文件的源码文件名称。在Java中,对于大多数的类来说,类名和文件名是一只的。
| 类型 | 名称 | 数量 |
|---|---|---|
| u2 | attribute_name_index | 1 |
| u4 | attribute_length | 1 |
| u2 | sourcefile_index | 1 |
sourcefile_index 数据项是指向常量池中CONSTANT_Utf8_info 型常量的索引,常量值是源码文件的文件名。
ConstantValue
ConstantValue 属性的作用是通知虚拟机自动变为静态变量赋值只有被static关键字修饰的变量才可以使用这项属性。
| 类型 | 名称 | 数量 |
|---|---|---|
| u2 | attribute_name_index | 1 |
| u4 | attribute_length | 1 |
| u2 | constantvalue_index | 1 |
在java中实例变量赋值和 静态变量赋值发生在不同的阶段:
对于实例变量
是在实例构造器 <init>()方法中进行的
对于类变量
在类构造器 <clinit> 或者 使用ConstantValue属性。
Oracle 实现 :
如果同时使用final和static 修饰一个变量,并且这个变量的数据类型是基本类型或者java.lang.String的话,就会生成ConstantValue 属性来进行初始化,如果没有被final修饰,或者并非基本类型及字符串会在 <clinit>中进行初始化。因为字面量中只有基本属性和字符串的字面量,所以ConstantValue 无法支持其他类型
| 类型 | 名称 | 数量 |
|---|---|---|
| u2 | attribute_name_index | 1 |
| u4 | attribute_length | 1 |
| u2 | constantvalue_index | 1 |
attribute_length 是一个固定值 为2字节
constantvalue_index 是 常量和字符串中的一种
InnerClasses
InnerClasses 属性用于记录内部类与宿主类之间的关联,如果一个类中定义了内部类,那编译器将会为它以及它所包含的内部类生成InnerClasses属性。
| 类型 | 名称 | 数量 |
|---|---|---|
| u2 | attribute_name_index | 1 |
| u4 | attribute_legnth | 1 |
| u2 | number_of_classes | 1 |
| inner_classes_info | inner_classes | number_of_classes |
number_of_classes 代表需要记录多少个内部类信息,每一个内部类信息都由一个inner_classes_info表进行描述。
| 类型 | 名称 | 数量 |
|---|---|---|
| u2 | inner_class_info_index | 1 |
| u2 | outer_class_info_index | 1 |
| u2 | inner_name_index | 1 |
| u2 | inner_class_access_flags | 1 |
inner_class_info_index 和 outer_class_info_index 都是指向常量池中CONSTANT_Class_info型常量的索引,分别代表了内部类和宿主类的符号索引
inner_name_index 是指向常量池中CONSTANT_Utf8_info型常量的索引,代表整个内部类的名称,如果是匿名内部类,这项值为0;
inner_class_access_flags 是内部类的访问标志。
| 标志名称 | 标志值 | 含义 |
|---|---|---|
| ACC_PUBLIC | 0x0001 | 内部类是否为public |
| ACC_PRIVATE | 0x0002 | 内部类是否为private |
| ACC_PROTECTED | 0x0004 | 内部类是否为protected |
| ACC_STATIC | 0x0008 | 内部类是否为static |
| ACC_FINAL | 0x0010 | 内部类是否为final |
| ACC_INTERFACE | 0x0200 | 内部类是否为接口 |
| ACC_ABSTRACT | 0x0400 | 内部类是否为abstract |
| ACC_SYNTHETIC | 0x1000 | 内部类是否由编译器产生 |
| ACC_ANNOTATION | 0x2000 | 内部类是否为注解类型 |
| ACC_ENUM | 0x4000 | 内部类是否为枚举类型 |
Deprecated及Synthetic
Deprecated表示某个类,字段或方法,已经被程序作者定为不再推荐使用,它可以通过代码中使用@deprecated注解进行设置
Synthetic属性代表此字段或者方法并不是由Java源码直接产生的,而是由编译器自行添加的
| 类型 | 名称 | 数量 |
|---|---|---|
| u2 | attribute_name_index | 1 |
| u4 | attribute_length | 1 |
StackMapTable
StackMapTable 中包含零至多个栈映射帧,每个栈映射帧都显式或隐式的代表了一个字节偏移量,用于表示执行到该字节码时,局部变量表和操作数栈的验证类型。
| 类型 | 名称 | 数量 |
|---|---|---|
| u2 | attribute_name_index | 1 |
| u4 | attribute_length | 1 |
| u2 | number_of_entries | 1 |
| stack_map_frame | stack_map_frame entries | number_of_entries |
Signature
signature用于记录泛型签名信息
| 类型 | 名称 | 数量 |
|---|---|---|
| u2 | attribute_name_index | 1 |
| u4 | attribute_length | 1 |
| u2 | signature_index | 1 |
aignature_index 必须是一个对常量池的有效索引,并且该项目必须是CONSTANT_Utf8_info 结构,
当 SigNature 是类文件属性 则表示是类签名,如果是方法表属性,则表示方法类型签名,如果是字段表属性,则表示字段类型签名
BootstrapMethods 属性
BootstrapMethods用于保存invokedynamic指令引用的引导方法限定符
| 类型 | 名称 | 数量 |
|---|---|---|
| u2 | attribute_name_index | 1 |
| u4 | attribute_length | 1 |
| u2 | num_bootstrap_methods | 1 |
| boostrap_method | bootstrap_methods | num_boostrap_methods |
num_boostrap_methods 给出引导方法限定符的数量
bootstrap_methods[]数组的每个成员包含了一个指向常量池CONSTANT_MethodHandle结构的索引值,它代表了一个引导方法
boostrap_method的表结构
| 类型 | 名称 | 数量 |
|---|---|---|
| u2 | bootstrap_method_ref | 1 |
| u2 | num_bootstrap_arguments | 1 |
| u2 | bootstrap_arguments | num_boostrap_arguments |
bootstrap_method_ref 必须是一个对常量池的有效索引,并且其指向的值是一个对常量池的有效索引。该索引必须是一个CONSTANT_MethodHandle_info结构
num_bootstrap_arguments 给出了boostrap_arguments[] 数组成员的数量
bootstrap_argumetns[] 数组中的每个成员必须是一个对常量池的有效索引。
MethodParaments
用于存储方法定义的参数名
| 类型 | 名称 | 数量 |
|---|---|---|
| u2 | attribute_name_index | 1 |
| u4 | attribute_length | 1 |
| u1 | parameters_count | 1 |
| parameter | parameters | parameters_count |
| 类型 | 名称 | 数量 |
|---|---|---|
| u2 | name_index | 1 |
| u2 | access_flags | 1 |
name_index 是一个指向常量池CONSTATN_Utf8_info常量的索引值,代表了该参数的名称。
access_flags是参数的状态指示器,它提供3种状态标识
0x0010 标识该参数被final修饰
0x1000 标识该参数并未出现在源文件中,由编译器自动生成
0x8000 标识该参数是在源文件中隐式定义的
模块化相关属性
| 类型 | 名称 | 数量 |
|---|---|---|
| u2 | attribute_name_index | 1 |
| u4 | attribute_length | 1 |
| u2 | module_name_index | 1 |
| u2 | module_flags | 1 |
| u2 | module_version_index | 1 |
| u2 | requires_count | 1 |
| require | requires | requires_count |
| u2 | exports_count | 1 |
| export | exports | exports_count |
| u2 | opens_count | 1 |
| open | opens | opens_count |
| use | uses_index | uses_count |
| u2 | provides_count | 1 |
| provide | provides | provides_count |
module_name_index 是一个指向常量池CONSTANT_Utf8_info常量的索引值,代表了该模块的名称。
module_flags 是模块的状态指示器。
0x0020 标识该模块是开放的
0x1000 标识该模块并未出现在源文件中,是编译器自动生成的
0x8000 标识该模块是在源文件中隐式定义的
module_version_index 是一个指向常量池CONSTANT_Utf8_info常量的索引值,代表了该模块的版本号
后续的requires,exports,opens,uses,provides定义结构基本相同
exports
| 类型 | 名称 | 数量 |
|---|---|---|
| u2 | exports_index | 1 |
| u2 | exports_flags | 1 |
| u2 | exports_to_count | 1 |
| export | exports_to_index | exports_to_count |
exports属性的每一个元素都代表一个被模块所导出的包,
exports_index 是一个指向常量池CONSTANT_Package_info常量的索引值,代表了被该模块导出的包
exports_flags 是该导出包的状态指示器
0x1000 该导出包并未出现在源文件中,是编译器自动生成的
0x8000 该导出包是在源文件中隐式定义的
exports_to_count 是该导出包的限定计数器,为0则是开放的,不为0则 exports_to_index 是以计数器为长度的数组,每个数组元素都是一个指向常量池中CONSTANT_Module_info常量的索引值,代表着只有这个数据范围内的模块才被允许访问该导出包的内容
ModulePackages
| 类型 | 名称 | 数量 |
|---|---|---|
| u2 | attribute_name_index | 1 |
| u4 | attirbute_length | 1 |
| u2 | package_count | 1 |
| u2 | package_index | package_count |
package_count是packageindexd数组的计数器,package_index中每个元素都是指向常量池CONSTATNT_Package_info常量的索引值。代表了模块中的一个包
ModuleMainClass
用于确定该模块的主类
| 类型 | 名称 | 数量 |
|---|---|---|
| u2 | attribute_name_index | 1 |
| u4 | attribute_length | 1 |
| u2 | main_class_index | 1 |
main_class_index 是一个指向常量池CONSTATN_Class_info常量的索引值,代表了该模块的主类
运行时注解相关属性
用于描述源码中的注解信息
以RuntimeVisibleAnnotations 为例 :
| 类型 | 名称 | 数量 |
|---|---|---|
| u2 | attribute_name_index | 1 |
| u4 | attribute_length | 1 |
| u2 | num_annotations | 1 |
| annotation | annotations | num_annotations |
num_annotations 是 annotations数组的计数器,annotations中每个元素都代表了一个运行时可见的注解,注解在Class文件中以annotation结构来存储。
| 类型 | 名称 | 数量 |
|---|---|---|
| u2 | type_index | 1 |
| u2 | num_element_value_pairs | 1 |
| element_value_pair | element_value_pairs | num_element_value_pairs |
type_index 是一个指向常量池CONSTANT_Utf8_info常量的索引值,该常量应以字段描述符的形式表示一个注解。
num_element_value_pairs是element_value_pairs数组的计数器,element_value_pairs中每个元素都是一个键值对,代表该注解的参数和值。