class文件是一组以8bit字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑的排列在class文件中,中间没有添加任何分隔符。当遇到需要占用8bit字节以上的数据项时,会按照高位在前的方式分割成若干个8bit字节进行存储。
ClassFile结构
类型 | 名称 | 数量 |
---|---|---|
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 | interfaces_count | 1 |
u2 | interfaces | interfaces_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 |
MagicNumber
固定值: cafe babe
- 作用是确定这个文件是否为一个能被jvm所接受的Class文件
MinorVersion和MajorVersion
minor version:小版本号
major version:大版本号
JDK版本 | 字节码中的主版本号(10进制) | 字节码中的主版本号(16进制) |
---|---|---|
1.2 | 46 | 0x002E |
1.3 | 47 | 0x002F |
1.4 | 48 | 0x0030 |
1.5 | 49 | 0x0031 |
1.6 | 50 | 0x0032 |
1.7 | 51 | 0x0033 |
1.8 | 52 | 0x0034 |
Constant Pool
常量池中主要存储两类常量:字面常量和符号引用。
字面量,比较接近java语言层面的常量概念,如文本字符串、被声明为final的常量值等
符号引用,包括了‘类和接口的全限定名’、‘字段的名称和描述符’、‘方法的名称和描述符’三类常量
常量类型
类型 | 值 | 描述 |
---|---|---|
CONSTANT_utf8_info | 1 | UTF-8编码的字符串 |
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 | 类中方法的符号引用 |
CONSTANT_InterfaceMethodref_info | 11 | 接口中方法的符号引用 |
CONSTANT_NameAndType_info | 12 | 字段或方法的符号引用 |
CONSTANT_MehodHandle_info | 15 | 方法句柄 |
CONSTANT_MethodType_info | 16 | 方法类型 |
CONSTANT_InvokeDynamic_info | 18 | 动态方法调用点 |
常量类型结构
CONSTANT_utf8_info{
u1 tag; //1
u2 length;
u1 bytes[length]
}
CONSTANT_Integer_info{
u1 tag; //3
u4 bytes; //int常量的值,按照Big-Endian的顺序存储
}
CONSTANT_Float_info{
u1 tag; //4
u4 bytes; //float常量的值,按照IEEE754单精度浮点标准存储
}
CONSTANT_Long_info{
u1 tag; //5
u4 high_bytes;
u4 low_bytes;
}
CONSTANT_Double_info{
u1 tag; //6
u4 high_bytes;
u4 low_bytes;
}
CONSTANT_Class_info{
u1 tag; //7
u2 name_index; //常量池索引,CONSTANT_utf8_info类型
}
CONSTANT_String_info{
u1 tag; //8
u2 string_index; //常量池索引,CONSTANT_utf8_info类型
}
CONSTANT_Fieldref_info{
u1 tag; //9
u2 class_index; // 常量池索引,CONSTANT_Class_info类型
u2 name_and_type_index; //常量池索引,CONSTANT_NameAndType_info类型
}
CONSTANT_Methodref_info{
u1 tag; //10
u2 class_index; //常量池索引,CONSTANT_Class_info类型
u2 name_and_type_index; //常量池索引,CONSTANT_NameAndType_info类型
}
CONSTANT_InterfaceMethodref_info{
u1 tag;//11
u2 class_index; // 常量池索引,CONSTANT_Class_info类型
u2 name_and_type_index;//常量池索引,CONSTANT_NameAndType_info类型
}
CONSTANT_NameAndType_info{
u1 tag;//12
u2 name_index; //常量池索引,CONSTANT_utf8_info类型,表示方法或字段名
u2 descriptor_index; //常量池索引,CONSTANT_utf8_info类型,表示字段类型
}
CONSTANT_MehodHandle_info{
u1 tag;//15
u1 reference_kind;
u2 reference_index;
}
CONSTANT_MethodType_info{
u1 tag;//16
u2 descriptor_index;
}
CONSTANT_InvokeDynamic_info{
u1 tag;//18
u2 bootstrap_method_attr_index;
u2 name_and_type_index;
}
AccessFlags
类修饰符,常量池后面紧跟的2个字节是Access Flags
字节码中的16进制 | 符号 | 含义 |
---|---|---|
0x0001 | ACC_PUBLIC | 是public类型 |
0x0010 | ACC_FINAL | 是final |
0x0020 | ACC_SUPER | 是否允许使用invokespecial字节码指令,JDK1.2以后编译出来的类这个标志为真 |
0x0200 | ACC_INTERFACE | 是一个接口 |
0x0400 | ACC_ABSTRACT | 是abstract类型 |
0x1000 | ACC_SYNTHETIC | 此类非由用户代码产生 |
0x2000 | ACC_ANNOTATION | 是一个注解 |
0x4000 | ACC_ENUM | 是一个枚举 |
This Class
access flags后面的2个字节,常量池索引值,指向的常量必须是CONSTANT_Class_info类型
Super Class
this class后面的2个字节,常量池索引,指向的常量必须是CONSTANT_Class_info类型
Interfaces
interface count: super class后面的2个字节,为0表示无实现接口
interfaces: interface count后面的n*2个字节(n个常量池索引),interface count 为0时无此数据
Fields
fields count: interfaces后面的2个字节,0表示无字段
fields: fields count后面的数据,字节数不定,由具体的field info决定
field info结构:
field_info {
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attributes_count];
}
字段修饰符表
字节码中的16进制 | 符号 | 含义 |
---|---|---|
0x0001 | ACC_PUBLIC | public |
0x0002 | ACC_PRIVATE | private |
0x0004 | ACC_PROTECTED | protected |
0x0008 | ACC_STATIC | static |
0x0010 | ACC_FINAL | final |
0x0040 | ACC_VOLATILE | volatile |
0x0080 | ACC_TRANSIENT | transient |
0x1000 | ACC_SYNCHETIC | 编译器自动产生 |
0x4000 | ACC_ENUM | enum |
字段描述符表
标识符 | 16进制 | 含义 |
---|---|---|
B | 42 | byte |
C | 43 | char |
D | 44 | double |
F | 46 | float |
I | 49 | int |
J | 4A | long |
S | 53 | short |
Z | 5A | boolean |
V | 56 | void |
L | 4C | 对象类型,例:Ljava/lang/Object; |
Methods
method_info{
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attributes_count];
}
方法修饰符表
字节码中的16进制 | 符号 | 含义 |
---|---|---|
0x0001 | ACC_PUBLIC | public |
0x0002 | ACC_PRIVATE | private |
0x0004 | ACC_PROTECTED | protected |
0x0008 | ACC_STATIC | static |
0x0010 | ACC_FINAL | final |
0x0020 | ACC_SYNCHRONIZED | synchronized |
0x0040 | ACC_BRIDGE | 由编译器产生的桥接方法 |
0x0080 | ACC_VARARGS | 接收不定参数 |
0x0100 | ACC_NATIVE | native |
0x0400 | ACC_ABSTRACT | abstract |
0x0800 | ACC_STRICT | strictfp |
0x1000 | ACC_XYNTHETIC | 由编译器自动产生 |
Attributes
属性表
属性名称 | 使用位置 | 含义 |
---|---|---|
Code | 方法 | java代码编译成的字节码指令 |
ConstantValue | 字段 | final关键字定义的常量值 |
Deprecated | 类、方法、字段 | 声明为deprecated |
Exceptions | 方法 | 方法抛出的异常 |
InnerClasses | 类 | 内部类列表 |
LineNumberTable | Code属性 | java源码的行号与字节码指令的对应关系 |
LocalVariableTable | Code属性 | 方法的局部变量描述 |
SourceFile | 类 | 源文件名称 |
Synthetic | 类、方法、字段 | 标识方法或字段为编译器自动生成 |
Code属性
Code_attribute{
u2 attribute_name_index;
u4 attribute_length;
u2 max_stack;
u2 max_locals;
u4 code_length;
u1 code[code_length];
u2 exception_table_length;
exception_info exception_table[exception_table_length];
u2 attributes_count;
attribute_info attributes[attributes_count]
}
attribute_length:属性值的长度,由于属性名称索引与属性长度一共是6个字节,所以属性值的长度固定为整个属性表的长度减去6个字节
max_stack:操作栈深度的最大值,虚拟机运行时根据此值来分配栈帧中的操作栈深度
max_locals:局部变量表所需的存储空间,单位是Slot。长度不超过32位的数据类型占用1个Slot,double、long 两个64位的数据类型需要2个Slot存放。方法参数、显式异常处理器的参数、方法体重定义的局部变量,都需要使用局部变量表存储。编译器会根据变量的作用域来分类Slot并分配给各个变量使用,然后计算出max_locals的大小。
code_length:字节码长度。理论值可以达2^32-1,但虚拟机规范限制一个方法不允许超过65535条字节码指令,超过后javac编译器就会拒绝编译。
code:存储字节码指令的字节流,每个指令占1个字节
exception_info{
u2 start_pc;
u2 end_pc;
u2 handler_pc;
u2 catch_type
}
ConstantValue属性
ConstantValue_attribute{
u2 attribute_name_index;
u4 attribute_length;
u2 constantvalue_index
}
Deprecated属性
Deprecated_attribute{
u2 attribute_name_index;
u4 attribute_length
}
Exceptions属性
Exceptions_attribute{
u2 attribute_name_index;
u4 attribute_length;
u2 number_of_exceptions;
u2 exception_index_table[number_of_exceptions]
}
InnerClasses属性
InnerClasses_attribute{
u2 attribute_name_index;
u4 attribute_length;
u2 numbers_of_classes;
inner_class_info inner_classes[number_of_classes]
}
inner_class_info{
u2 inner_classes_info_index;
u2 outer_classes_info_index;
u2 inner_name_index;
u2 inner_name_access_flags
}
内部类修饰符
字节码中的16进制 | 符号 | 含义 |
---|---|---|
0x0001 | ACC_PUBLIC | public |
0x0002 | ACC_PRIVATE | private |
0x0004 | ACC_PROTECTED | protected |
0x0008 | ACC_STATIC | static |
0x0010 | ACC_FINAL | final |
0x0020 | ACC_SYNCHRONIZED | synchronized |
0x0400 | ACC_ABSTRACT | abstract |
0x1000 | ACC_XYNTHETIC | 由编译器自动产生 |
0x2000 | ACC_ANNOTATION | 注解 |
0x4000 | ACC_ENUM | 枚举 |
LineNumberTable属性
LineNumberTable_attribute{
u2 attribute_name_index;
u4 attribute_length;
u2 line_number_table_length;
line_number_info line_number_table[line_number_table_length]
}
line_number_table_length:行号个数
line_number_info:行号信息
line_number_info{
u2 start_pc;
u2 line_number;
}
LocalVariableTable属性
LocalVariableTable_attribute{
u2 attribute_name_index;
u4 attribute_length;
u2 local_variable_table_length;
local_variable_info local_variable_table[local_variable_table_length]
}
local_variable_table_length: 局部变量个数
local_variable_info:局部变量信息
local_variable_info{
u2 start_pc;
u2 length;
u2 name_index;
u2 descriptor_index;
u2 index
}
start_pc:局部变量的声明的字节码行号
length: 变量作用域覆盖长度
name_index: 变量名索引
descriptor_index: 变量描述符索引
index:局部变量在栈帧局部变量表中slot的位置。当该变量数据类型为64位类型时,它占用的Slot为index和index+1两个位置
SourceFile属性
SourceFile_attribute{
u2 attribute_name_index;
u4 attribute_length;
u2 sourcefile_index
}
Synthetic属性
Synthetic_attribute{
u2 attribute_name_index;
u4 attribute_length
}
字节码分析示例
来源:CSDN
作者:可乐要加冰啊
链接:https://blog.csdn.net/weixin_37641677/article/details/103988043