🔯 类文件结构
2022年6月9日
- Java
🔯 类文件结构
1. Class 文件概述
Class 文件是一组以字节为基础单位的二进制流
- 我们俗称的 字节码 指的是 方法表中的
Code
属性的内容
- 我们俗称的 字节码 指的是 方法表中的
Class 文件格式:
ClassFile {
u4 magic; //Class 文件的标志
u2 minor_version;//Class 的小版本号
u2 major_version;//Class 的大版本号
u2 constant_pool_count;//常量池的数量
cp_info constant_pool[constant_pool_count-1];//常量池
u2 access_flags;//Class 的访问标记
u2 this_class;//当前类
u2 super_class;//父类
u2 interfaces_count;//接口
u2 interfaces[interfaces_count];//一个类可以实现多个接口
u2 fields_count;//Class 文件的字段属性
field_info fields[fields_count];//一个类可以有多个字段
u2 methods_count;//Class 文件的方法数量
method_info methods[methods_count];//一个类可以有个多个方法
u2 attributes_count;//此类的属性表中的属性数
attribute_info attributes[attributes_count];//属性表集合
}
- 数据类型:
- 无符号数
u1
: 1 个字节的无符号数u2
: 2 个字节的无符号数u4
u8
- 表
- 由 多个 无符号数 + 表 组成的符合数据结构
- 以
_info
结尾 - 紧跟着表数据之前会使用一个前置的容量计数器来记录表中元素的个数
- 无符号数
名称 | 2 字节 | 2 字节 |
---|---|---|
魔数 | CA FE | BA BE |
次 & 主版本号 | 00 00 | 00 34 |
常量池 | 00 04 | 常量 1 |
常量 2 | 常量 3 | |
访问标志 | 常量 4 | access flags |
类 | 当前类常量池索引 | 父类常量池索引 |
接口 | 00 03 | 接口 1 |
接口 2 | 接口 3 | |
字段 | 00 03 | 字段 1 |
字段 2 | 字段 3 | |
方法 | 00 03 | 方法 1 |
方法 2 | 方法 3 | |
属性 | 00 03 | 属性 1 |
属性 2 | 属性 3 |
2. 魔数
- 固定值
CA FE BA BE
- 作用
- 确定该文件是否是一个能被虚拟机接受的 Class 文件
3. 版本号
1) 次版本号
- JDK 1.2 之后 - JDK 12 之前固定为 0
JDK 12
次版本号若 ==65535
说明为公测版本,并未列入正式特性清单
2) 主版本号
- JDK 8 == 52 转为 16进制 == 34
- 依次递增
4. 常量池
- 常量数 count
u2
16进制
- 常量
- 下标从 [1] - [count]
- len = count
- 最后一位下标 == len - 1 = count - 1
- long & double 占用 2 个下标位置
- 存放常量类型:
- 字面量:
- 文本字符串
- 被声明为 final 的常量等
- 符号引用:
- 包
- 类 & 接口的全限定名
- 字段的名称 & 描述符
- 方法的名称 & 描述符
- 方法句柄 & 方法类型
- 动态调用点 & 动态常量
- 字面量:
5. 访问标志
- 用于识别类 & 接口层次的访问信息
- 举例
ACC_PUBLIC
ACC_FINAL
ACC_INTERFACE
ACC_ABSTRACT
ACC_ANNOTATION
ACC_ENUM
ACC_MODULE
6. 当前类 & 父类
- 通过当前类 | 父类的值确定对应常量池的下标
- 通过常量池下标找到该常量
- 通过该常量内部的索引找到对应类的全限定名
- 除了
java.lang.Object
外,所有 Java 类均有父类,因此父类索引 != 0
7. 字段 & 方法 & 属性
- 均通过 计数器 + 表内容 形式表示
{
u2 fields_count;
field_info fields[fields_count];
}
- 具体内容形式类似如下
{
u2 access_flags; // 访问标志
u2 name_index; // 名称在常量池中的索引
u2 descriptor_index; // 类型在常量池中的索引
u2 attributes_count; // 属性个数
attribute_info attributes[attributes_count]; // 属性项集合
}
- 属性表
- 字段表中的属性表
- 记录的是字段是否为常量、字段上是否有注解等信息
- 方法表中的属性表
- 记录了方法上是否有注解、方法的异常信息声明、字节码等信息
- Class 文件的属性表
- 记录了类的源文件名称、类上标记的注解信息、内部类等信息
- 方法表中的 方法内容 中的
attribute_info
中有一项属性为 Code
Code
就是 我们俗称的 字节码- 因此,
字节码是Class文件的一部分