Class文件是一组以8个字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在文件之中,中间没有添加任何分隔符。当遇到需要占用8个字节以上空间的数据项时,则会按照高位在前的方式分割成若干个8个字节进行存储。
Class文件格式采用类似于C语言结构体的伪结构体来存储数据,这种伪结构体只有两种数据类型:
01|Class文件构成
- 无符号数
无符号数数据基本数据类型,以u1、u2、u4、u8来分别代表1个字节、2个字节、4个字节和8个字节的无符号数,无符号数可以用来描述数字、索引引用、数量值或者按照UTF-8编码构成字符串值
- 表
表是由多个无符号数或者其他表作为数据项构成的复合数据类型,用于描述有层次关系的复合结构的数据,整个Class文件可以看作如下一张表:
类型 | 名称 | 数量 |
---|---|---|
u4 | magic | 1 |
u2 | minor_version | 1 |
u2 | major_version | 1 |
u2 | constant_pool_count | 1 |
cp_info | constant_pool | constant_pool_count-1 |
u2 | access_flags | 1 |
u2 | this_class | 1 |
u2 | super_class | 1 |
u2 | interfaces_count | 1 |
u2 | interfaces | interfaces_count |
u2 | fields_count | 1 |
field_info | fields | fields_count |
u2 | methods_count | 1 |
method_info | methods | methods_count |
u2 | attributes_count | 1 |
attribute_info | attributes | attributes_count |
表中的数据项,无论是顺序还是数量,都是被严格限定的,皆不允许改变。
Magic与Class文件版本(magic、minor_version、major_version)
- Magic:占4个字节
每个Class文件的前4个字节被称为Magic Number,用于确定这个文件是否为一个能被虚拟机接受的Class文件,值固定为0xCAFEBABE。
存放如文本字符串、被声明为final的常量值等
- 符号引用(Symbolic References)
- 被模块导出或者开放的包
- 类和接口的全限定名
- 字段的名称和描述符
- 方法的名称和描述符
- 方法句柄和方法类型
- 动态调用点和动态常量
访问标志(access_flags)
用于识别类或者接口层次的访问信息,访问标示如下表:
标志名称 | 标准值 | 含义 |
---|---|---|
ACC_PUBLICK | 0x0001 | 是否为public类型 |
ACC_FINAL | 0x0010 | 是否为final |
ACC_SUPER | 0x0020 | 是否允许使用invokespecial字节码指令的新语意 |
ACC_INTERFACE | 0x0200 | 标识这是一个接口 |
ACC_ABSTRACT | 0x0400 | 是否为abstract |
ACC_SYNTHETIC | 0x1000 | 标识这个类并非有用户代码生成 |
ACC_ANNOTATION | 0x2000 | 标识这是一个注解 |
ACC_ENUM | 0x4000 | 标示这是一个枚举 |
ACC_MODULE | 0x8000 | 标示这是一个模块 |
类索引(this_class)、父类索引(super_class)与接口索引集合(interfaces)
Class文件中由这三项数据来确定该类型的继承关系。类索引用于确定这个类的全限定名,父类索引用于确定这个类的父类的全限定名
字段表集合(fields)
用于描述接口或者类中声明的变量,不包括在方法内部声明的局部变量。