一、Class 文件的整体特点
Class 文件是一组以 8 个字节为基础单位的二进制流,数据紧凑排列,无分隔符。其采用类似 C 语言结构体的伪结构存储数据,包含 “无符号数” 和 “表” 两种数据类型。无符号数用于描述数字、索引引用等,表则由多个无符号数或其他表构成,用于描述复合结构数据,整个 Class 文件本质上也可看作一张表。
二、魔数与 Class 文件的版本
- 魔数:每个 Class 文件的头 4 个字节是魔数,值为 0xCAFEBABE,用于确定文件是否为虚拟机可接受的 Class 文件。这个魔数在 Java 还叫 “Oak” 语言时就已确定,据说与著名咖啡品牌 Peet’s Coffee 的 Baristas 咖啡有关。
- 版本号:紧接魔数的 4 个字节是版本号,第 5、6 字节为次版本号,第 7、8 字节为主版本号。Java 版本号从 45 开始,高版本 JDK 能向下兼容低版本 Class 文件,但不能运行高版本 Class 文件。例如,JDK 1.1 支持 45.0 - 45.65535 版本的 Class 文件,JDK 1.2 支持 45.0 - 46.65535 的 Class 文件
三、常量池
- 常量池概述:常量池可看作 Class 文件的资源仓库,是与其他项目关联最多、占用空间较大且第一个出现的表类型数据项目。常量池入口有一项 u2 类型数据表示容量计数值,从 1 开始计数。
常量池结构
- 常量类型:常量池主要存放字面量(如文本字符串、final 常量值)和符号引用(包括被模块导出或开放的包、类和接口全限定名、字段和方法的名称及描述符等)。
- 常量结构:常量池中每一项常量都是一个表,截至 JDK 13 有 17 种不同类型的常量。每种常量表结构起始的 u1 类型标志位代表常量类型。例如,标志位为 0x07 的 CONSTANT_Class_info 类型常量代表类或接口的符号引用,其 name_index 指向 CONSTANT_Utf8_info 类型常量,该常量表示类或接口的全限定名。CONSTANT_Utf8_info 类型常量的 length 值表示 UTF-8 编码字符串长度,后面跟着相应长度的字符串,且 UTF-8 缩略编码有其特定规则。
表 CONSTANT_Class_info型常量的结构
表 CONSTANT_Utf8_info型常量的结构
- 常量分析工具:借助 JDK 的 bin 目录下的 javap 工具,使用 verbose 参数可分析 Class 文件字节码。分析结果中有些常量是编译器自动生成的,会被字段表、方法表、属性表引用,用于描述方法返回值、参数等信息。