Class 文件的结构_java

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
1UTF-8 编码的字符串
CONSTANT_Integer_info3
整型字面量
CONSTANT_Float_info4
浮点型字面量
CONSTANT_Long_info5长整型字面量
CONSTANT_Double_info6
双精度浮点型字面量
CONSTANT_Class_info7类或接口的符号引用
CONSTANT_String_info
8
字符串类型字面量
CONSTANT_Fieldref_info9
字段的符号引用
CONSTANT_Methodref_info10
类中的方法的符号引用
CONSTANT_InterfaceMethodref_info11接口方法的符号引用
CONSTANT_NameAndType_info12字段或方法的部分符号引用
CONSTANT_MethodHandle_info15
方法句柄
CONSTANT_MethodType_info16
方法类型
CONSTANT_Dynamic_info17
动态计算常量
CONSTANT_InvokeDynamic_info18
动态方法调用点
CONSTANT_Module_info19
模块
CONSTANT_Package_info20
模块中开发或导出的包
  • 常量池存放字面量(Literal)和符号引用(Symbolic References)
  • 特点:Class 文件中最大数据项目之一、第一个出现表数据结构



4、访问标志

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

描述
ACC_PUBLIC
0x0001
public 类型
ACC_FINAL0x0010final 类
ACC_SUPER0x0020使用 invokespecial
ACC_INTERFACE
0x0200接口
ACC_ABSTRACT0x0400abstract 类型
ACC_SYNTHETIC0x1000
非 Java 代码产生
ACC_ANNOTATION0x2000注解
ACC_ENUM0x4000枚举
ACC_MODULE0x8000
模块


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

  • 类索引(this_class)、父类索引(super_class),u2
  • 接口索引集合(interfaces),u2 集合
  • 类索引确定类的全限定名、父类索引确定父类的全限定名、接口索引集合确定实现接口
  • 索引值在常量池中查找对应的常量


6、字段表(field_info)集合

  • 描述接口或类申明的变量
  • fields_count,u2,表示字段表数量;后面接着相应数量的字段表
  • 9 种字段访问标志
标志

描述
ACC_PUBLIC
0x0001
public 字段
ACC_PRIVATE0x0002
private 字段
ACC_PROTECTED0x0004protected 字段
ACC_STATIC0x0008static 字段
ACC_FINAL0x0010final 字段
ACC_VOLATILE0x0040volatile 字段
ACC_TRANSIENT0x0080transient 字段
ACC_SYNTHENTIC0x1000编译器生成字段
ACC_ENUM0x4000enum 字段
  • 字段表结构

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


7、方法表(method_info)集合

  • 描述接口或类申明的方法
  • methods_count,u2,表示方法表数量;后面接着相应数量的方法表
  • 12 种方法访问标志
标志

描述
ACC_PUBLIC
0x0001
public 方法
ACC_PRIVATE0x0002
private 方法
ACC_PROTECTED0x0004protected 方法
ACC_STATIC0x0008static 方法
ACC_FINAL0x0010final 方法
ACC_SYNCHRONIZED0x0020synchronized 方法
ACC_BRIDGE0x0040编译器产生的桥接方法
ACC_VARARGS0x0080接受不定参数
ACC_NATIVE0x0100native 方法
ACC_ABSTRACT0x0400abstract 方法
ACC_STRICT0x0800strictfp 方法
ACC_SYNTHENTIC0x1000编译器生成方法
  • 方法表结构与字段表结构一致


8、属性表(attribute_info)集合

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

模块的信息
ModuleMainClass

指定模块的主类
NestHost

内部类得知宿主类
NestMembers

宿主类得知内部类


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

类型
名称数量
u4
magic1
u2minor_version
1
u2
major_version
1
u2
constant_pool_count1
cp_info
constant_pool
constant_pool_count-1
u2
access_flags
1
u2
this_class
1
u2super_class1
u2
interface_counts1
u2
interfaces
interface_counts
u2
fields_count1
field_infofieldsfields_count
u2
methods_count
1
method_infomethods
methods_count
u2attributes_count
1
attribute_info
attributesattributes_count


整理自《深入理解 Java 虚拟机