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