1.class文件概述
Class文件是一组以8位字节为基础单位的二进制流,各个数据项目按照顺序紧凑的摆列在Class文件之中,中间没有添加任何分隔符,整个Class文件中存储的内容几乎全部是程序运行的必要数据,没有空隙存在当遇到8位字节以上的空间的数据项时,则会按照高位在前的方式分割成若干个8位字节进行存储。Class文件中有两类数据类型,分别是无符号数和表,具体包括:魔数,Class文件版本,常量池,访问标志,类索引,父类索引,接口索引集合,字段表集合,方法表集合,属性表集合。
2.class文件格式
类型 | 名称 | 数量 |
u4 | magic | 1 |
u2 | minor_version | 1 |
u2 | major_version | 1 |
u2 | constant_pool_count | 1 |
cp_info | constant_pool | constant_pool_count - 1 |
u2 | access_flags | 1 |
u2 | this_class | 1 |
u2 | super_class | 1 |
u2 | interface_count | 1 |
u2 | interfaces | interface_count |
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.魔数
字节码的前四个字节标识文件的类型,用于在执行Class文件时校验文件是否为class文件,.class的文件魔数为CAFEBABE。
4.Class文件版本
魔数后4个字节表示的是Class文件的版本,后面两位表示主版本号,前面3个字节为次版本号。对应关系如下表:
JDK1.8 | 52 |
JDK1.7 | 51 |
JDK1.6 | 50 |
JDK1.5 | 49 |
JDK1.4 | 48 |
JDK1.3 | 47 |
JDK1.2 | 46 |
JDK1.1 | 45 |
5.常量池
版本号后2个字节为常量池的长度。之后为常量池。
cp_info format | ||
type | descriptor | remark |
u1 | tag | |
u1 | info[] |
CONSTANT_Methodref_info 用于记录方法信息(包括类中定义的方法以及代码中使用到的方法) | ||
type | descriptor | remark |
u1 | tag | CONSTANT_Methodref(10) |
u2 | class_index | constant_pool中的索引,CONSTANT_Class_info类型。记录定义该方法的类。 |
u2 | name_and_type_index | constant_pool中的索引,CONSTANT_NameAndType_info类型。指定类中纯方法名(name)和方法描述符(descriptor) |
CONSTANT_fieldref_info | ||
type | descriptor | remark |
u1 | tag | |
u2 | index | |
u2 | index |
CONSTANT_Class_info 用于记录类或接口名 | ||
type | descriptor | remark |
u1 | tag | CONSTANT_ClassI(7) |
u2 | name_index | constant_pool中的索引,CONSTANT_utf8_info类型。表式类或接口名。 |
CONSTANT_Utf8_info | ||
type | descriptor | remark |
u1 | tag | |
u2 | length | |
u1 | bytes |
各常量池和index对应关系如下表:
CONSTANT_Utf8_info | 1 |
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 |
CONSTATN_Interfacemethodref | 11 |
CONSTANT_NameAndType_info | 12 |
CONSTATN_MethodHandle_info | 15 |
CONSTANT_MethodType_info | 16 |
CONSTANT_Dynamic_info | 18 |
6.访问标志符
java字节码用两个字节来表示访问标志。
Flag Name | Value | Remarks |
ACC_PUBLIC | 0x0001 | public |
ACC_FINAL | 0x0010 | final |
ACC_SUPER | 0x0020 | 用于兼容早期编译器,新编译器都没有设置该标记,以在使用invokespecial指令时对子类方法做特定处理。 |
ACC_INTERFACE | 0x0200 | 接口,同时需要设置:ACC_ABSTRACT。不可同时设置ACC_FINAL、ACC_SUPER、ACC_ENUM。 |
ACC_ABSTRACT | 0x0400 | 抽象类,无法实例化。不可与ACC_FINAL同时设置。 |
ACC_SYNTHETIC | 0x1000 | synthetic,由编译器产生,不存在于源代码中。 |
ACC_ANNOTATION | 0x2000 | 注解类型,需同时设置:ACC_INTERFACE、ACC_ABSTRACT。 |
ACC_ENUM | 0x4000 | 枚举类型 |
this_class:类索引,super_class:父类索引,interface_count:类实现的接口数量,interfaces:类实现的接口索引。
8.字段表集合
字段表用于描述接口或者类中声明的变量。
一个类中字段的作用域,静态或者非静态,可变形,并发可见性,是否可以序列化都由一个2个字节的access_flags标识,数据类型由descriptor_index标识,字段名称由name_index标识,其他属性由attribute_count和attribute_info标识。
8.方法表集合
方法表集合用来描述类或接口中定义的方法。
Method_info {
acccess_flags u2 --访问标志
name_index u2 --方法名索引
description_index u2 --方法描述索引
attributes_count u2 --属性表长度
attribute_info u2 --属性表信息
}
9.属性表集合
属性表集合用来补充表述字段表和方法表中的信息。
attribute_info {
attribute_name_index u2 --属性名索引
attribute_length u4 --属性长度
info u1 --属性信息
}