目录
1.前序
本文主要针对jvm的字节码文件做一个字典类型的记录,方便以后学习使用。本文所有的表格均出自《深入理解Java虚拟机》这本书的第六章内容。
另外,对于一个class文件,jvm提供了一个命令,对其进行反编译,他便是"javap -v. classs文件"通过这个命令,你还发现在字节码的世界里有需要许多不为人知的秘密。
2.总表
2.1class文件格式
类型 | 名称 | 数量 |
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 | surper_class | 1 |
u2 | interfaces_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 |
2.2 常量池格式表
常量 | 项目 | 类型 | 描述 |
CONSTANT_Utf8_info | tag | u1 | 值为1 |
length | u2 | UTF-8编码的字符串占用的字节数 | |
bytes | u1 | 长度为length的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_String_info | tag | u1 | 值为8 |
index | u2 | 指向字符串字面量的索引 | |
CONSTANT_Fieldref_info | tag | u1 | 值为9 |
index | u2 | 指向声明字段的类或者接口描述符CONSTANT_Class_info的索引项 | |
index | u2 | 指向字段描述符CONSTANT_NameAndType的索引项 | |
CONSTANT_Methodref_info | tag | u1 | 值为10 |
index | u2 | 指向声明方法的类或者接口描述符CONSTANT_Class_info的索引项 | |
index | u2 | 指名称及类型CONSTANT_NameAndType的索引项 | |
CONSTANT_InterfaceMethodref_info | tag | u1 | 值为11 |
index | u2 | 指向声明方法的接口描述符CONSTANT_Class_info的索引项 | |
index | u2 | 指名称及类型CONSTANT_NameAndType的索引项 | |
CONSTANT_NameAndType_info | tag | u1 | 值为12 |
index | u2 | 指向该字段或方法名称常量项的索引 | |
index | u2 | 指向该字段或方法描述符常量项的索引 | |
CONSTANT_MethodHandle_info | tag | u1 | 值为15 |
reference_kind | u1 | 值必须在1-9之间(包括1和9),它决定了方法句柄的类型,方法句柄类型的值表示方法句柄的字节码行为 | |
reference_index | u2 | 值必须是对常量池的有效索引 | |
CONSTANT_MethodType_info | tag | u1 | 值为16 |
descriptor_index | u2 | 值必须是对常量池的有效索引,常量池在该索引处的项必须是CONSTANT_Utf-8_info结构,表示方法的描述符 | |
CONSTANT_Invoke-Dynamic_info | tag | u1 | 值为18 |
bootstrap_method_attr_index | u2 | 值必须是对当前Class文件中引导方法表的bootstrap_methods[]数组的有效索引 | |
name_and_type_index | u2 | 值必须是对当前常量池的有效索引,常量池在该所引处的项必须是CONSTANT_NameAndType_info结构,表示方法名和方法描述符 | |
注: 1.由于常量个数不固定,所以需要放置一个u2格式的数据; 2.他其他容量计数器不同的是,常量基数从1开始,也许是null的引用(仅仅猜测) 3.常量池主要包含字面量和符号引用。字面量接近于java层面的常量概念;符号引用则属于编译原理方面概念(类和接口的全限定名、字段名称和描述符、方法的名称和描述符)。 |
2.3 类访问标志
标志名称 | 标志量 | 含义 |
ACC_PULIC | 0x0001 | 是否为public类型 |
ACC_FINAL | 0x0010 | 是否被声明为final,只有类可设置 |
ACC_SUPER | 0x0020 | 是否允许使用invokesecial字节码指令的新语意,invokespecial指令的语意在JDK1.0.2发生过改变,为了区别这了指令使用哪种语意,JDK1.0.2之后编译出来的类的这个标志都必须为真。 |
ACC_INTERFACE | 0x0200 | 标识这是一个接口 |
ACC_ABSTRACT | 0x0400 | 是否abstract类型,对于接口或者抽象类来说,此标志值为真,其他类型为假 |
ACC_SYNTHERIC | 0x1000 | 标识这个类并非由用户代码产生的 |
ACC_ANNOTATION | 0x2000 | 标识这是个注解 |
ACC_ENUM | 0x4000 | 标识这是个枚举 |
3.字段表
3.1 字段表结构
类型 | 名称 | 数量 |
u2 | access_flags | 1 |
u2 | name_index | 1 |
u2 | descriptor_index | 1 |
u2 | attributes_count | 1 |
attribute_info | attributes | attributes_count |
3.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_SYNTHETIC | 0x1000 | 字段是否由编译器自动产生的 |
ACC_ENUM | 0x4000 | 字段是否enum |
3.3 描述符标识字符含义
标识字符 | 含义 | 标识字符 | 含义 |
B | 基本类型byte | J | 基本类型long |
C | 基本类型char | S | 基本类型short |
D | 基本类型double | Z | 基本类型boolean |
F | 基本类型float | V | 特殊类型void |
I | 基本类型int | L | 对象类型,如Ljava/lang/Object |
注: 对于数组类型,每一维度将使用一个前置的“[”字符来描述,如一个定义为“java.lang.String[][]”类型的二维数组,将被记录为“[[java/lang/String”,一个整型数组“int[]”将被记录为“[I” |
4.方法表
4.1 方法表结构
类型 | 名称 | 数量 |
u2 | access_flags | 1 |
u2 | name_index | 1 |
u2 | descriptor_index | 1 |
u2 | attributes_count | 1 |
attribute_info | attributes | attributes_count |
4.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_VARARGS | 0x0080 | 方法是否接受不定参数 |
ACC_NATIVE | 0x0100 | 方法是否为native |
ACC_ABSTRACT | 0x0400 | 方法是否abstract |
ACC_STRICTFP | 0x0800 | 方法是否为strictfp |
ACC_SYNTHETIC | 0x1000 | 方法是否由编译器自动产生的 |
4.3 属性表
1)Code属性表的结构
类型 | 名称 | 数量 |
u2 | attribute_name_index | 1 |
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 |
2)异常表的属性结构
类型 | 名称 | 数量 |
u2 | start_pc | 1 |
u2 | end_pc | 1 |
u2 | handler_pc | 1 |
u2 | catch_pc | 1 |
3)Exception属性结构
类型 | 名称 | 数量 |
u2 | attribute_name_index | 1 |
u4 | attribute_length | 1 |
u2 | number_of_exceptions | 1 |
u2 | exception_index_table | number_of_exceptions |
4)LineNumberTable属性结构
类型 | 名称 | 数量 |
u2 | attribute_name_index | 1 |
u4 | attribute_length | 1 |
u2 | line_number_table_length | 1 |
line_number_info | line_number_table | line_number_table_length |
注: line_number_table是一个数量为line_number_table_length、类型为line_number_info的集合,line_number_info表包含了start_pc和line_number两个u2类型的数据项,前者是字节码行号,后者是java源码行号。 |
5)LocalVariableTable属性结构
类型 | 名称 | 数量 |
u2 | attribute_name_index | 1 |
u4 | attribute_length | 1 |
u2 | local_variable_table_length | 1 |
local_variable_info | local_variable_table | local_variable_table_length |
6)local_variable_info项目结构
类型 | 名称 | 数量 |
u2 | start_pc | 1 |
u2 | length | 1 |
u2 | name_index | 1 |
u2 | descriptor_index | 1 |
u2 | index | 1 |
7)SourceFile属性结构表
类型 | 名称 | 数量 |
u2 | attribute_name_index | 1 |
u4 | attribute_length | 1 |
u2 | sourcefile_index | 1 |
8)ConstantValue属性结构表
类型 | 名称 | 数量 |
u2 | attribute_name_index | 1 |
u4 | attribute_length | 1 |
u2 | constantvalue_index | 1 |
9)InnerClasses属性结构表
类型 | 名称 | 数量 |
u2 | attribute_name_index | 1 |
u4 | attribute_length | 1 |
u2 | number_of_classes | 1 |
inner_classes_info | inner_classes | number_of_classes |
10)inner_classes_info表的结构
类型 | 名称 | 数量 |
u2 | inner_class_info_index | 1 |
u2 | outer_class_info_index | 1 |
u2 | inner_name_index | 1 |
u2 | inner_class_access_flags | 1 |
11)inner_class_access_flags标志
标志名称 | 标志值 | 含义 |
ACC_PUBLIC | 0x0001 | 内部类是否public |
ACC_PRIVATE | 0x0002 | 内部类是否private |
ACC_PROTECTED | 0x0004 | 内部类是否protected |
ACC_STATIC | 0x0008 | 内部类是否static |
ACC_FINAL | 0x0010 | 内部类是否final |
ACC_INTERFACE | 0x0020 | 内部类是否synchronized |
ACC_ABSTRACT | 0x0400 | 内部类是否abstract |
ACC_SYNTHETIC | 0x1000 | 内部类是否由编译器自动产生的 |
ACC_ANNOTATION | 0x2000 | 内部类是否是一个注解 |
ACC_ENUM | 0x4000 | 内部类是否是一个枚举 |
12)Deprecated及Synthetic属性结构
类型 | 名称 | 数量 |
u2 | attribute_name_index | 1 |
u4 | attribute_length | 1 |
13)StackMapTable 属性的结构
类型 | 名称 | 数量 |
u2 | attribute_name_index | 1 |
u4 | attribute_length | 1 |
u2 | number_of_entries | 1 |
stack_map_frame | stack_map_frame_entries | number_of_entries |
14)Signature属性的结构
类型 | 名称 | 数量 |
u2 | attribute_name_index | 1 |
u4 | attribute_length | 1 |
u2 | signature_index | 1 |
15)BootstrapMethods属性结构
类型 | 名称 | 数量 |
u2 | attribute_name_index | 1 |
u4 | attribute_length | 1 |
u2 | num_bootstrap_methods | 1 |
Bootstrap-method | bootstrap_methods | num_bootstrap_methods |
16)bootstrap_method属性的结构
类型 | 名称 | 数量 |
u2 | bootstrap_method_ref | 1 |
u2 | num_bootstrap_arguments | 1 |
u2 | bootstrap_arguments | num_bootstrap_arguments |