Class 文件的结构

2020-11-23

Class 文件包含了 Java 虚拟机的指令集、符号表、辅助信息的字节码(Byte Code),是实现跨操作系统和语言无关性的基石之一。

一个 Class 文件定义了一个类或接口的信息,是以 8 个字节为单位,没有分隔符,按顺序紧凑排在一起的二进制流。

用 "无符号数" 和 "表" 组成的伪结构来存储数据。

  • 无符号数:基本数据类型,用来描述数字、索引引用、数量值、字符串值,如u1、u2 分别表示 1 个字节、2 个字节

  • 表:无符号数和其他表组成,命名一般以 "_info" 结尾

 

组成部分

1、魔数 Magic Number

  • Class 文件头 4 个字节,0xCAFEBABE

  • 作用是确定该文件是 Class 文件

 

2、版本号

  • 4 个字节,前 2 个是次版本号 Minor Version,后 2 个主版本号 Major Version

  • 从 45 (JDK1.0) 开始,如 0x00000032 转十进制就是 50,代表 JDK 6

  • 低版本的虚拟机跑不了高版本的 Class 文件

 

3、常量池

  • 常量容量计数值(constant_pool_count),u2,从 1 开始。如 0x0016 十进制 22 代表有 21 项常量

  • 每项常量都是一个表,目前 17 种

类型 标志 描述
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_Fieldref_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 模块中开发或导出的包
  • 常量池存放字面量(Literal)和符号引用(Symbolic References)

  • 特点:Class 文件中最大数据项目之一、第一个出现表数据结构

 

 

4、访问标志

  • 2 个字节,表示类或接口的访问标志

标志 描述
ACC_PUBLIC 0x0001 public 类型
ACC_FINAL 0x0010 final 类
ACC_SUPER 0x0020 使用 invokespecial
ACC_INTERFACE 0x0200 接口
ACC_ABSTRACT 0x0400 abstract 类型
ACC_SYNTHETIC 0x1000 非 Java 代码产生
ACC_ANNOTATION 0x2000 注解
ACC_ENUM 0x4000 枚举
ACC_MODULE 0x8000 模块

 

 

5、类索引、父类索引、接口索引集合

  • 类索引(this_class)、父类索引(super_class),u2

  • 接口索引集合(interfaces),u2 集合

  • 类索引确定类的全限定名、父类索引确定父类的全限定名、接口索引集合确定实现接口

  • 索引值在常量池中查找对应的常量

 

 

6、字段表(field_info)集合

  • 描述接口或类申明的变量

  • fields_count,u2,表示字段表数量;后面接着相应数量的字段表

  • 9 种字段访问标志

标志 描述
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_SYNTHENTIC 0x1000 编译器生成字段
ACC_ENUM 0x4000 enum 字段
  • 字段表结构

类型 名称 数量
u2 access_flags 1
u2 name_index 1
u2 descripor_index 1
u2 attributes_count 1
attribute_info attributes attributes_count

 

7、方法表(method_info)集合

  • 描述接口或类申明的方法

  • methods_count,u2,表示方法表数量;后面接着相应数量的方法表

  • 12 种方法访问标志

标志 描述
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_VARARGS 0x0080 接受不定参数
ACC_NATIVE 0x0100 native 方法
ACC_ABSTRACT 0x0400 abstract 方法
ACC_STRICT 0x0800 strictfp 方法
ACC_SYNTHENTIC 0x1000 编译器生成方法
  • 方法表结构与字段表结构一致

 

8、属性表(attribute_info)集合

  • class 文件、字段表、方法表可携带属性集合,描述特有信息

  • 预定义 29 项属性,可自定义写入不重名属性

属性名称 使用位置 描述
Code 方法表 Java代码编译的字节码指令
ConstantValue 字段表 final 关键字定义的常量值
Deprecated 类、方法表、字段表 过期作废的类、方法和字段
Exceptions 方法表 方法抛出的异常
EnclosingMethod 类文件 局部类或匿名类拥有,标识外围方法
InnerClass 类文件 内部类列表
LineNumberTable Code属性 Java源码的行号与字节码指令的对应关系
LocalVariableTable Code属性 方法的局部变量描述
StackMapTable Code属性 检查和处理目标方法局部变量与操作数栈所需类型是否匹配
Signature 类、方法表、字段表 源文件名称
SourceDebugExtension 类文件 存储额外的调试信息
Synthetic 类、方法表、字段表 标识方法或字段为编译器自动生成
LocalVariableTypeTable 描述泛型参数化类型
RuntimeVisibleAnnotations 类、方法表、字段表 指明运行时可见的注解
RuntimeInvisibleAnnotations 类、方法表、字段表 指明运行时不可见的注解
RuntimeVisibleParameterAnnotation 方法表 指明方法参数运行时可见的注解
RuntimeInvisibleParameterAnnotation 方法表 指明方法参数运行时不可见的注解
AnnotationDefault 方法表 用于记录注解类元素的默认值 
BootstrapMethods 类文件 保存invokeddynamic指令引用的引导方式限定符
RuntimeVisibleTypeAnnotation 类、方法表、字段表 指明运行时可见的类注解
RuntimeInvisibleTypeAnnotation 类、方法表、字段表 指明运行时不可见的类注解
MethodParameters 方法表 方法名称编译进Class文件,可运行时获取
Module 模块的信息
ModuleMainClass 指定模块的主类
NestHost 内部类得知宿主类
NestMembers 宿主类得知内部类


Class 文件可以看作一张表,如下

ConstXiong 备案号:苏ICP备16009629号-3