Java Class文件解析
一、描述
Class文件是一组以8位(1字节)为基础单位的二进制流。
当数据项大于8位时,按照【高位在前】分割成若干个8位进行存储。
按照Java虚拟机规范的规定,Class文件结构只有两种数据类型:无符号数和表
二、无符号数
无符号数属于基本的数据类型,以u1、u2、u4、u8来分别代表1字节,2字节,4字节,8字节的无符号数。
无符号数可用来描述数字、索引引用、数量值或者按照UTF-8编码构成字符串值。
三、表
| 类型 | 名字 | 名称 | 数量 | 描述 |
| u4 | magic | 魔数 | 1 | Class文件1-4字节,是否能被JVM接受,更加安全 |
| u2 | minor_version | 次版本号 | 1 | Class文件5-6字节 |
| u2 | major_version | 主版本号 | 1 | Class文件7-8字节(52对应JDK1.8) |
| u2 | constant_pool_count | 常量池大小 | 1 | 从1开始,第0项常量为空:不引用任何一个常量池项目 |
| cp_info | constant_pool | 常量池 | constant_pool_count - 1 |
字面量:字符串、常量值等 符号引用:类和接口的全限定名;字段名称和描述符;方法名称和描述符 |
| u2 | access_flag | 类访问标志 | 1 | ACC_PUBLIC |
| u2 | this_class | 类索引 | 1 | 确定类的全限定名 |
| u2 | super_class | 父类索引 | 1 | 确定类的父类的全限定名(除Object,所有类的父类索引不为0) |
| u2 | interfaces_count | 接口数量 | 1 | 确定接口数量 |
| u2 | interfaces | 接口索引集合 | interfaces_count | 确定类实现了那些接口;如果数量为0,则不占用任何字节 |
| u2 | fields_count | 字段数量 | 1 | 确定字段数量 |
| field_info | fields | 字段集合 | fields_count | 描述接口或类中声明的表量;类变量、实例表量 |
| u2 | methods_count | 方法数量 | 1 | 确定方法数量 |
| method_info | methods | 方法集合 | methods_count | 描述接口或者类中方法 |
| u2 | attributes_count | 属性数量 | 1 | 确定属性数量 |
| attribute_info | attributes | 属性集合 | attributes_count | 描述属性 |
3.1 常量池项目
| 常量 | 项目 | 类型 | 描述 |
| CONSTANT_Utf8_info | tag | u1 | 1 |
| length | u2 | 字符串字节数(UTF-8编码) | |
| bytes | u1 | 字符串(UTF-8编码) | |
| CONSTANT_Integer_info | tag | u1 | 3 |
| bytes | u4 | int(高位在前) | |
| CONSTANT_Float_info | tag | u1 | 4 |
| bytes | u4 | float(高位在前) | |
| CONSTANT_Long_info | tag | u1 | 5 |
| bytes | u8 | long(高位在前) | |
| CONSTANT_Double_info | tag | u1 | 6 |
| bytes | u8 | double(高位在前) | |
| CONSTANT_Class_info | tag | u1 | 7 |
| index | u2 | 指向全限定名常量项的索引(CONSTANT_Utf8_info) | |
| CONSTANT_String_info | tag | u1 | 8 |
| index | u2 | 指向字符串字面量的索引(CONSTANT_Utf8_info) | |
| CONSTANT_Fieldref_info | tag | u1 | 9 |
| index | u2 | 指向声明字段的类或接口描述符的索引(CONSTANT_Class_info) | |
| index | u2 | 指向字段描述符的索引(CONSTATN_NameAndType_info) | |
| CONSTANT_Methodref_info | tag | u1 | 10 |
| index | u2 | 指向声明方法的类描述符的索引(CONSTANT_Class_info) | |
| index | u2 | 指向方法的名称及类型描述符的索引(CONSTANT_NameAndType_info) | |
| CONSTANT_InterfaceMethodref_info | tag | u1 | 11 |
| index | u2 | 指向声明方法的接口描述符的索引(CONSTANT_Class_info) | |
| index | u2 | 指向方法的名称及类型描述符的索引(CONSTANT_NameAndType_info) | |
| CONSTANT_NameAndType_info | tag | u1 | 12 |
| index | u2 | 指向字段或方法名称常量项的索引(CONSTANT_Utf8_info) | |
| index | u2 | 指向字段或方法描述符常量项的索引(CONSTANT_Utf8_info) | |
| CONTANT_MethodHandle_info | tag | u1 | 15 |
| reference_kind | u1 | 1-9;决定方法句柄类型;标识方法句柄的字节码行为 | |
| reference_index | u2 | 对常量池的有效索引 | |
| CONSTANT_MethodType_info | tag | u1 | 16 |
| descriptor_index | u2 | 对常量池的有效索引,方法的描述符(CONSTANT_Utf8_info) | |
| CONSTANT_InvokeDynamic_info | tag | u1 | 18 |
|
bootstrap_method _attr_index |
u2 | 对当前Class文件中引导方法的bootstrap_methods[]数组的索引 | |
|
name_and_type_ index |
u2 |
对当前常量池的有效索引,方法名称和方法描述符 (CONSTANT_NameAndType_info) |
3.2 描述符标识字段含义
| 标识字符 | 含义 |
| B | 基本数据类型(byte) |
| C | 基本数据类型(char) |
| D | 基本数据类型(double) |
| F | 基本数据类型(float) |
| I | 基本数据类型(int) |
| J | 基本数据类型(long) |
| S | 基本数据类型(short) |
| Z | 基本数据类型(boolean) |
| V | 特殊类型(void) |
| L | 对象类型(Ljava/lang/Object)([[Ljava/lang/Object) |
3.3类访问标志
| 标志名称 | 标志值 | 含义 |
| ACC_PUBLIC | 0x0001 | 是否是public类型 |
| ACC_FINAL | 0x0010 | 是否是final类型(类) |
| ACC_SUPER | 0x0020 |
是否允许使用invokespecial字节码指令的新语意 (JDK 1.0.2之后编译出来的类为真) |
| ACC_INTERFACE | 0x0200 | 标识接口 |
| ACC_ABSTRACT | 0x0400 | 是否是abstract类型(接口和抽象类为真) |
| ACC_SYNTHETIC | 0x1000 | 标识类不由用户生成 |
| ACC_ANNOTATION | 0x2000 | 标识注解 |
| ACC_ENUM | 0x4000 | 标识枚举 |
3.4.1 字段表集合
| 类型 | 名称 | 数量 | 备注 |
| u2 | access_flags | 1 | 字段访问标志 |
| u2 | name_index | 1 | 字段简单名称(CONSTANT_Utf8_info) |
| u2 | descriptor_index | 1 | 字段的描述符(CONSTANT_Utf8_info) |
| u2 | attributes_count | 1 | 属性数量 |
| attribute_info | attributes | attributes_count | 字段访问标志的集合 |
3.4.2 字段访问标志
| 标志名称 | 标志值 | 含义 |
| 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_SYNTHEIC | 0x1000 | 字段是否由编译器自动产生 |
| ACC_ENUM | 0x4000 | 字段是否enum |
3.5.1 方法表集合
| 类型 | 名称 | 数量 | 备注 |
| u2 | access_flags | 1 | 方法访问标志(ACC_PUBLIC) |
| u2 | name_index | 1 | 方法简单名称(CONSTANT_Utf8_info) |
| u2 | desciptor_index | 1 | 方法的描述符(CONSTANT_Utf8_info) |
| u2 | attributes_count | 1 | 属性数量 |
| attribute_info | attributes | attributes_count | 属性集合 |
3.5.2 方法访问标志
| 标志名称 | 标志值 | 含义 |
| 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_VARARGE | 0x0080 | 方法是否接受不定参数 |
| ACC_NATIVE | 0x0100 | 方法是否native |
| ACC_ABSTRACT | 0x0400 | 方法是否abstract |
| ACC_STRICTFP | 0x0800 | 方法是否strictfp |
| ACC_SYNTHETIC | 0x1000 | 方法是否由编译器自动产生 |
3.6 属性表
3.6.1 Code属性
| 类型 | 名称 | 数量 | 备注 |
| u2 | attribute_name_index | 1 | 属性名称索引(CONSTANT_Utf8_info) |
| u4 | attribute_length | 1 | 属性长度 |
| u2 | max_stack | 1 | |
| u2 | max_locals | 1 | |
| u4 | code_length | 1 | |
| u1 | code | code_length | |
| u2 | exception_table_length | 1 | |
| exception_info | exception_table | exception_table_length | |
| u2 | attributes_count | 1 | |
| attribute_info | attributes | attributes_count |
3.6.2 Exception
| 类型 | 名称 | 数量 | 备注 |
| u2 | attribute_name_index | 1 | |
| u4 | attribute_length | 1 | |
| u2 | number_of_exceptions | 1 | 异常数量 |
| u2 | exception_index_table | number_of_exception | 异常(CONSTANT_Class_info) |

浙公网安备 33010602011771号