一:字节码结构组成部分:
结构层 | 占用字节 | 说明 | |
魔数 | Magic Number | 4 | oxCAFEBABE |
次版本号 | minor version | 2 | |
主版本号 | major version | 2 | java8对应52 |
常量池常量个数 | constant pool count | 2 | |
常量池表 | Constant Pool | 常量个数-1 | 标识出所有当前类所用的的信息,组成列表一一对应 PS: 常量0:表示null,作为保留字段,并没有列入常量池 |
类访问标识符 | Access Flags | 2 | 描述当前类的访问控制权限 |
当前类名 | This Class Name | 2 | |
当前类的父类名 | Super Class Name | 2 | |
实现接口个数 | interfaces count | 2 | |
当前类实现的接口名 | Interfaces | 接口个数 | PS:如果实现的接口个数是0,则无此项信息 |
属性字段信息个数 | fields count | 2 | |
属性字段信息 | Fields | fields count | |
方法个数 | methods count | 2 | |
方法信息 | Methods | methods count | |
附加属性的个数 | attributes count | 2 | |
属性 | Attributes | attributes count |
二:字节码常量池数组结构类型:
项目 | 占用字符 | 描述 |
tag | 1 | 值为1 (UTF-8编码的字符串) |
length | 2 | UTF-8 编码的字符串长度 |
bytes | 1 | 长度为leng 的UTF-8的编码字符串 |
tag | 1 | 值为3(整形字面量) |
bytes | 4 | 按照高位在前存储的int值 |
tag | 1 | 值为4(浮点型字面量) |
bytes | 4 | 按照高位在前存储的float值 |
tag | 1 | 值为5(长整型字面量) |
bytes | 8 | 按照高位在前存储的long值 |
tag | 1 | 值为6(双精度浮点型字面量) |
bytes | 8 | 按照高位在前存储的double值 |
tag | 1 | 值为7(类或接口的符号引用) |
bytes | 2 | 指向全限定名常量项的索引 |
tag | 1 | 值为8(字符串类型字面量) |
bytes | 2 | 指向字符串字面量的索引 |
tag | 1 | 值为9(字段的符号引用) |
index | 2 | 指向声明字段的娄或者接口描述符Constant_class_info的索引项 |
index | 2 | 指向字段描述符Constant_nameAndType_info的索引项 |
tag | 1 | 值为10(类中方法的符号引用) |
index | 2 | 指向声明方法的类描述符Constant_Class_info 的索引项 |
index | 2 | 指向名称及类型描述符Constant_nameAndType_info的索引项 |
tag | 1 | 值为11(接口中方法的符号引用) |
index | 2 | 指向声明方法的接口描述符Constant_class_info的索引项 |
index | 2 | 指向名称及类型描述符Constant_nameAndType_info的索引项 |
tag | 1 | 值为12(字段或方法的符号引用) |
index | 2 | 指向该字段或方法名称常量项的索引 |
index | 2 | 指向该字段或方法描述符常量项的索引 |
tag | 1 | 值为15(表示方法句柄) |
refefence_kind | 1 | 值必须为[1,9]的范围,表示方法句柄的字节码行为 |
reference_index | 2 | 指向常量池的索引 |
tag | 1 | 值为16(标志方法类型) |
descriptor_index | 2 | 指向常量池的索引,表示方法的描述符 |
tag | 1 | 值为18(表示一个动态方法调用点) |
boostrap_method_attr_index | 2 | 值必须是对当前Class文件中引导方法表的bootrap_method[]数组的有效索引 |
name_and_type_index | 2 | 指向常量池的索引,表示方法名和方法描述符 |
三:java 字节码中类,属性,方法的访问标识符:
PS: 类的访问标识是通过以上8种之间进行与(|)运算得出来的结果,比如0x0011,它表示 该类是一个public且为final 修辞的类
四:字段表结构:
名称 | 占用字节 | 描述 |
access_flag | 2 | 访问标识 |
name_index | 2 | 字段名索引值 |
descriptor_index | 2 | 字段描述索引值 |
attributes_count | 2 | 附加属性个数 |
attributes | n | 附加属性结构,如果属性个数为0,则当前结构不存在 |
五:方法表信息结构:
名称 | 占用字节 | 描述 | |||
access_flag | 2 | 访问标识 | |||
name_index | 2 | 方法名索引值 | |||
descriptor_index | 2 | 方法描述索引值 | |||
attributes_count | 2 | 附加属性个数 | |||
attributes | n | 附加属性结构,如果属性个数为0,则当前结构不存在 | |||
Code | attribute_name_index | 2 | 附加属性名索引值 | ||
attribute_length | 4 | 附加属性长度,表示后面存在该长度个字节 | |||
max_stack | 2 | 表示方法运行的任何时刻所能达到的操作数栈最大深度 | |||
max_locals | 2 | 表示局部变量表所需的存储空间,单位是Slot | |||
code_length | 4 | 表示该方法所包含的字节码的字节数以及具体的指令码 | |||
code[code_length] | code_length | code_length有多大,表示这里面就有多少个指令 | |||
exception_table_length | 2 | 异常表长度(个数) | |||
exception_table | start_pc | 2 | start_pc 和end_pc 表示在code 数组中的从start_pc 到end_pc(前包后不包) 处的指令抛出的异常会由这个表项来处理 | ||
end_pc | 2 | ||||
handler_pc | 2 | 表示处理异常的代码开始处 | |||
catch_type | 2 | 表示会被处理的异常类型,它指向常量池的一个异常类。当catch_type为0时,表示处理所有的异常 | |||
attribute_count | 2 | 附加属性表个数 | |||
LineNumberTable (这个属性用来表示code数组中的字节码和java代码行数之间的关系,在调试程序时用来定位执行代码行数) | attribute_name_index | 2 | 附加属性名索引值 | ||
attribute_length | 4 | 附加属性长度 | |||
line_number_table_length | 2 | line_number_table 的长度 | |||
line_number_table | start_pc | 2 | 字节码行号 | ||
line_number | 2 | 源代码行号 | |||
LocalVariableTable (描述栈帧中局部变量表中的变量与Java源码中定义的变量之间的关系) | attribute_name_index | 2 | 附加属性名索引值 | ||
attribute_length | 4 | 附加属性长度 | |||
local_variable_table_length | 2 | 局部变量表个数 | |||
local_variable_table | start_pc | 2 | 表示局部变量的生命周期开始的字节码偏移量 | ||
length | 2 | 表示局部变量的生命周期开始的字节码作用范围覆盖的长度 | |||
name_index | 2 | 指向常量池索引,表示局部变量名称 | |||
Descriptor_index | 2 | 指向常量池索引,表示局部变量的描述符 | |||
index | 2 | 描述局部变量在栈帧局部变量表中Slot的位置 |
六:属性表包含的属性及其所属结构位置
属性名称 | 使用位置 | 含义 |
Code | 方法表 | Java代码编译成的字节码指令 |
ConstantValue | 字段表 | final关键字定义的常量池 |
Deprecated | 类,方法,字段表 | 被声明为deprecated的方法和字段 |
Exceptions | 方法表 | 方法抛出的异常 |
EnclosingMethod | 类文件 | 仅当一个类为局部类或者匿名类是才能拥有这个属性,这个属性用于标识这个类所在的外围方法 |
InnerClass | 类文件 | 内部类列表 |
LineNumberTable | Code属性 | Java源码的行号与字节码指令的对应关系 |
LocalVariableTable | Code属性 | 方法的局部便狼描述 |
StackMapTable | Code属性 | JDK1.6中新增的属性,供新的类型检查检验器检查和处理目标方法的局部变量和操作数有所需要的类是否匹配 |
Signature | 类,方法表,字段表 | 用于支持泛型情况下的方法签名 |
SourceFile | 类文件 | 记录源文件名称 |
SourceDebugExtension | 类文件 | 用于存储额外的调试信息 |
Synthetic | 类,方法表,字段表 | 标志方法或字段为编译器自动生成的 |
LocalVariableTypeTable | 类 | 使用特征签名代替描述符,是为了引入泛型语法之后能描述泛型参数化类型而添加 |
RuntimeVisibleAnnotations | 类,方法表,字段表 | 为动态注解提供支持 |
RuntimeInvisibleAnnotations | 表,方法表,字段表 | 用于指明哪些注解是运行时不可见的 |
RuntimeVisibleParameterAnnotation | 方法表 | 作用与RuntimeVisibleAnnotations属性类似,只不过作用对象为方法 |
RuntimeInvisibleParameterAnnotation | 方法表 | 作用与RuntimeInvisibleAnnotations属性类似,作用对象哪个为方法参数 |
AnnotationDefault | 方法表 | 用于记录注解类元素的默认值 |
BootstrapMethods | 类文件 | 用于保存invokeddynamic指令引用的引导方式限定符 |
七:各种属性的数据结构:
其基本结构:
类型 | 名称 | 数量 |
u2 | attribute_name_index | 1 |
u4 | attribute_length | 1 |
u1 | info | attribute_length |
具体结构类型如下:
属性类别 | 名称 | 占用字节 | 描述 | |
SourceFile | attribute_name_index | 2 | 属性名,其值指向常量池的第n个常量 | |
attribute_length | 4 | 属性长度后面所占字节数 | ||
sourcefile_index | 2 | 源文件名,其值指向常量池的第n个常量 | ||
ConstantValue | attribute_name_index | 2 | 属性名,其值指向常量池的第n个常量 | |
attribute_length | 4 | 该值必须固定为2 | ||
constantvalue_index | 2 | 指向常量池字面量常量 | ||
InnerClasses | attribute_name_index | 2 | 属性名,其值指向常量池的第n个常量 | |
attribute_length | 4 | 属性长度后面所占字节数 | ||
number_of_classes | 2 | 表示需要记录多少个内部类信息 | ||
inner_classes_info | inner_class_info_index | 2 | 表示指向内部类的符号引用,其值指向常量池第n个常量 | |
outer_class_info_index | 2 | 表示指向宿主类的符号引用,其值指向常量池第n个常量 | ||
inner_name_index | 2 | 表示内部类名称,其值指向常量池第n个常量,如果是匿名内部类,则该值为0 | ||
inner_class_access_flags | 2 | 内部类访问标志,与类访问标识类似 | ||
Deprecated | attribute_name_index | 2 | 属性名,其值指向常量池的第n个常量 | |
attribute_length | 4 | 属性长度后面所占字节数,该值固定为:0x00000000 | ||
Synthetic | attribute_name_index | 2 | 属性名,其值指向常量池的第n个常量 | |
attribute_length | 4 | 属性长度后面所占字节数,该值固定为:0x00000000 | ||
StackMapTable | attribute_name_index | 2 | 属性名,其值指向常量池的第n个常量 | |
attribute_length | 4 | 属性长度后面所占字节数 | ||
number_of_entries | 2 | 栈映射表个数 | ||
stack_map_frame_entries | number_of_entries | 栈映射表信息 | ||
Signature | attribute_name_index | 2 | 属性名,其值指向常量池的第n个常量 | |
attribute_length | 4 | 属性长度后面所占字节数 | ||
signature_index | 2 | 表示类签名,方法类型签名或字段类型签名,指向常量池的常量 | ||
BootstrapMethods | attribute_name_index | 2 | 属性名,其值指向常量池的第n个常量 | |
attribute_length | 4 | 属性长度后面所占字节数 | ||
num_bootstrap_methods | 2 | bootsrap_methods 的个数 | ||
bootstrap_method | bootstrap_method_ref | 2 | 指向常量索引,并且该索引类型必须是:CONSTANT_MethodHandle_info 结构 | |
num_bootsrap_arguments | 2 | 表示bootstrap_arguments 数组的个数 | ||
bootstrap_arguments | 2 | bootsrap_arguments 数组中指向常量池的有效索引 |