🔯 类文件结构

吞佛童子2022年6月9日
  • Java
  • JVM
大约 3 分钟

🔯 类文件结构

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 0000 34
常量池00 04常量 1
常量 2常量 3
访问标志常量 4access 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. 当前类 & 父类

  • 通过当前类 | 父类的值确定对应常量池的下标
  • 通过常量池下标找到该常量
  • 通过该常量内部的索引找到对应类的全限定名
  1. 除了 java.lang.Object 外,所有 Java 类均有父类,因此父类索引 != 0

7. 字段 & 方法 & 属性

  1. 均通过 计数器 + 表内容 形式表示
{
    u2 fields_count;
    field_info fields[fields_count];
}
  1. 具体内容形式类似如下
{
    u2 access_flags; // 访问标志
    u2 name_index; // 名称在常量池中的索引
    u2 descriptor_index; // 类型在常量池中的索引
    u2 attributes_count; // 属性个数
    attribute_info attributes[attributes_count]; // 属性项集合
}
  1. 属性表
  • 字段表中的属性表
    • 记录的是字段是否为常量、字段上是否有注解等信息
  • 方法表中的属性表
    • 记录了方法上是否有注解、方法的异常信息声明、字节码等信息
  • Class 文件的属性表
    • 记录了类的源文件名称、类上标记的注解信息、内部类等信息
  1. 方法表中的 方法内容 中的 attribute_info 中有一项属性为 Code
  • Code 就是 我们俗称的 字节码
  • 因此,字节码是Class文件的一部分
上次编辑于: 2022/10/10 下午8:43:48
贡献者: liuxianzhishou