Class文件结构

狂风中的少年 提交于 2020-01-16 05:12:09

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

  1. 作用是确定这个文件是否为一个能被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
}

字节码分析示例

字节码分析示例

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!