一、概述
Java的源码编译后的class文件,具有非常严谨的结构,文件各个部分内容的完整性也通过自身描述来校验。
开始描述class文件内容前,我们先定义一些说明:u1代表一个字节,也是两个16进制字符,u2、u4、u8分别代表2、4、8个字节
二、类文件整体结构
名称 | 类型*长度 | 字段含义 |
魔数 | u4 * 1 | 固定值,十六进制表示是CAFEBABE,表示该文件是一个class文件,装载类文件的时候就会校验前四个字节是不是该魔数 |
minor version | u2 * 1 | 次版本号 |
major version | u2 * 1 | 主版本号,jvm在加载class文件后,会判断当前虚拟机版本是否可以处理此class文件,jvm只能处理某个版本以下版本的class文件,因为高版本的class文件可能会新加了很多特性,老的vm是识别不了的。此处某版本的计算方式是,对于1.X版本的虚拟机,只能处理major版本号<= 44+X的class文件。如1.5的vm只能处理49及以下的class文件 |
constant_pool_count | u2 * 1 | 常量池entry(入口、条)的数目 |
constant_pool | cp_info * (constant pool count-1) | 常量池存储的字面量literal、整数、浮点数、类名、方法名、类描述符、方法描述符、字段名、字段描述符等 |
access_flag | u2 * 1 |
该类/接口的访问标示,一共有ACC_FINAL、ACC_PUBLIC、ACC_ABSTRACT、ACC_INTERFACE、ACC_SUPER、ACC_SYNTHETIC、ACC_ANNOTATION、ACC_ENUM 8种类型 |
this_class | u2 * 1 |
当前类型信息,指向常量池中类型为Class的entry |
super_class | u2 * 1 |
超类信息,指向常量池中类型为Class的entry |
interface_count | u2 * 1 | 实现的接口的数目 |
interfaces | u2 * interface_count | 实现的接口信息,每一项都指向常量池中的类型为Class的entry |
field_count | u2 * 1 |
该类/接口中字段个数 |
fields | field_info * field_count | 字段信息,每一项都是一个field_info结构 |
method_count | u2 * 1 | 方法数量 |
methods | method _info * method_count | 方法数量,每一项都是一个method_info结构 |
attribute_count | u2 * 1 | 属性的个数 |
attributes | attribute_info * attribute_count | 属性,每一项都是一个attribute_info结构 |
二、常量池
常量池共有12中类型:Constant_Utf8_info、Constant_Integer_info、Constant_Float_info、Constant_Long_info、Constant_Double_info、Constant_String_info、Constant_Class_info、Constant_Fieldref_info、Constant_Methodref_info、Constant_InterfaceMethodref_info、Constant_NameAndType_info。每种常量info都是如下格式:
名称 | 类型 * 数量 | 含义 |
tag | u1 * 1 | 用来标示类型,不同类型的tag值不同 |
info | info * 1 | 根据不同的tag,info信息不同 |
1、Constant_Utf8_info,表示字面量
名称 | 类型 * 数量 | 含义 |
tag | u1 * 1 | 取值1 |
length | u1 * 1 | 字面量值的长度 |
bytes | u1 * length | 字面量值 |
2、Constant_Integer_info,表示整型值
名称 | 类型 * 数量 | 含义 |
tag | u1 * 1 | 取值3 |
length | u4 * 1 | integer的值 |
3、Constant_Float_info,表示单精度浮点类型
名称 | 类型 * 数量 | 含义 |
tag | u1 * 1 | 取值4 |
length | u4 * 1 | float的值 |
4、Constant_Long_info,表示long值
名称 | 类型 * 数量 | 含义 |
tag | u1 * 1 | 取值5 |
length | u8 * 1 | long值 |
5、Constant_Double_info,表示双精度浮点型值
名称 | 类型 * 数量 | 含义 |
tag | u1 * 1 | 取值6 |
length | u4 * 1 | double值 |
6、Constant_Class_info,表示类型信息
名称 | 类型 * 数量 | 含义 |
tag | u1 * 1 | 取值7 |
name_index | u2 * 1 | 指向全限定名的索引,全限定名存储在Constant_Utf8_info中 |
7、Constant_String_info,表示字符串
名称 | 类型 * 数量 | 含义 |
tag | u1 * 1 | 取值8 |
string_index | u2 * 1 | 指向字符串字面量(Constant_Utf8_info)的索引 |
8、Constant_Fieldref_info,表示引用到的别的类的字段信息,注意是引用到的,不是自己类的
名称 | 类型 * 数量 | 含义 |
tag | u1 * 1 | 取值9 |
class_index | u2 * 1 | 字段所属的类,指向Constant_Class_info的索引 |
name_and_type_index | u2 * 1 | 方法描述符,指向Constant_NameAndType_info的索引 |
9、Constant_Methodref_info,表示引用到的方法信息
名称 | 类型 * 数量 | 含义 |
tag | u1 * 1 | 取值10 |
class_index | u2 * 1 | 方法所属的类,指向Constant_Class_info的索引 |
name_and_type_index | u2 * 1 | 方法描述符,指向Constant_NameAndType_info的索引 |
10、Constant_InterfaceMethodref_info,表示引用到的接口方法信息
名称 | 类型 * 数量 | 含义 |
tag | u1 * 1 | 取值11 |
interface_index | u2 * 1 | 方法所属的接口,指向Constant_Class_info的索引 |
name_and_type_index | u2 * 1 | 方法描述符,指向Constant_NameAndType_info的索引 |
11、Constant_NameAndType_info,表示字段或方法的描述符信息,包括名称和描述
名称 | 类型 * 数量 | 含义 |
tag | u1 * 1 | 取值12 |
name_index | u2 * 1 | 方法、字段的名称,指向Constant_Utf8_info的索引 |
descriptor_index | u2 * 1 | 方法、字段的描述符,如([I,[java\lang\String) v 指向Constant_Utf8_info的索引 |
三、字段,当前类/接口的字段信息
名称 | 类型 * 数量 | 含义 |
access_flag | u2 * 1 | 访问标示,ACC_PRIVATE、 ACC_PROTECTED、 ACC_PUBLIC、 ACC_FINAL、 ACC_STATIC、 ACC_SYNTHETIC、 ACC_VOLATILE、 ACC_TRANSIENT、ACC_ENUM |
name_index | u2 * 1 | 字段名称,指向常量池Constant_Utf8_info的索引 |
descriptor_index | u2 * 1 | 描述符信息,指向常量池Constant_Utf8_info的索引,取值B、 C、 D、 F、 I、 J、 S、 Z、 V、 L |
attribute_count | u2 * 1 | 属性数量 |
attributes | attribute_info * attribute_count | 属性信息,可以有ConstantValue、Synthetic、Deprecated、Signature、RuntimeVisibleAnnotations、RuntimeInvisibleAnnotations |
四、方法,当前类/接口的方法信息
名称 | 类型 * 数量 | 含义 |
access_flag | u2 * 1 | 访问标示,ACC_PRIVATE、 ACC_PROTECTED、 ACC_PUBLIC、 ACC_FINAL、 ACC_STATIC、 ACC_SYNTHETIC、 ACC_ABSTRACT、 ACC_SYNCHRONIZED、ACC_VARARGS、 ACC_NATIVE、 ACC_STRICT、 ACC_BRIDGE |
name_index | u2 * 1 | 字段名称,指向常量池Constant_Utf8_info的索引 |
descriptor_index | u2 * 1 | 描述符信息,指向常量池Constant_Utf8_info的索引,取值B、 C、 D、 F、 I、 J、 S、 Z、 V、 L |
attribute_count | u2 * 1 | 属性数量 |
attributes | attribute_info * attribute_count | 属性信息,可以有Synthetic、Deprecated、Code、Signature、RuntimeVisibleAnnotations、 RuntimeVisibleParameterAnnotation、 RuntimeInvisibleAnnotations、RuntimeInvisibleParameterAnnotation、Exceptions、AnnotationDefault |
五、属性,此处属性包括类属性和方法、字段属性
名称 | 类型 * 数量 | 含义 |
name_index | u2 * 1 | 属性名称,指向常量池Constant_Utf8_info的索引 |
attribute_length | u2 * 1 | 属性长度,用来控制后续访问字节的数量 |
info | info * 1 | 属性信息,不同的attribute信息不同 |
类的attribute有SourceFile存储源码文件信息-g:none/-g:source关开、InnerClass内部类信息、Deprecated、Synthetic、EnclosingMethod局部类匿名类的访问范围、Signature泛型特征签名、SourceDebugExtension额外调试信息如jsp调试、RuntimeVisibleAnnotations运行时可见的Annotation、RuntimeInvisibleAnnotations运行时不可见的Annotation、LocalVariableTypeTable使用特征签名代替描述符
另外还有一些描述Attribute本身的attribute,比如Code就包含有LineNumberTable、LocalVariableTable
此处不详细列出attribute