java虚拟机5 字节码
java字节码本质是java程序的格式化表示,便于机器处理。所以他是java程序的另一种表示,java程序包含的信息他都包含并且更加结构化。
java虚拟机字节码格式:
magic
魔数,标识该文件是一个字节码文件。
minor_version
major_version
字节码的版本号
constant_pool
常量池,存储字节码中的常量数据以及符号引用。常量数据包括有utf8、Integer、float、long、double几种类型。符号引用包括有class、field、method
因为java在编译的时候,不像c有连接的过程,虚拟机加载的时候是动态连接,所以需要存储符号引用以便虚拟机加载的时候进行连接。
access_flags
访问标识。
this_class
类索引,指向一个常量池中的class类型
super_class
父类索引,指向一个常量池中的class类型
interfaces
接口索引,指向多个常量池中的class类型
fields
字段,存储类的字段定义。
methods
方法,存储类的方法定义。
attributes
属性表用于存储class文件、字段、方法的专有信息,如下所示。字段和方法都有自己的属性定义。
cp_info
常量池格式,
常量 | 项目 | 类型 | 描述 |
utf8 | tag | u1 | 1 |
length | u2 | 字符串字节数 | |
bytes | u1 | 长度位length的字符串 | |
integer | tag | u1 | 3 |
bytes | u4 | int值 | |
float | tag | u1 | 4 |
bytes | u4 | float值 | |
long | tag | u1 | 5 |
bytes | u8 | long值 | |
double | tag | u1 | 6 |
bytes | u8 | double值 | |
class | tag | u1 | 7 |
index | u2 | 全限定名常量项索引 | |
string | tag | u1 | 8 |
index | u2 | 字符串索引 | |
fieldref | tag | u1 | 9,代码中引用到的字段 |
index | u2 | 常量池class引用,表示引用的字段是哪个类的 | |
index | u2 | 常量池nameAndType引用,表示引用的字段的名称和参数类型 | |
methodref | tag | u1 | 10,代码中引用到的方法 |
index | u2 | 常量池class引用,表示引用的方法是哪个类的 | |
index | u2 | 常量池nameAndType引用,表示引用的方法名和参数类型 | |
interfaceMethodref | tag | u1 | 11,代码中引用到的接口方法 |
index | u2 | 常量池class引用,表示引用的方法是哪个接口的 | |
index | u2 | 常量池nameAndType引用,表示引用的方法名和参数类型 | |
nameAndType | tag | u1 | 12 |
index | u2 | 指向utf8常量池,表示名称 | |
index | u2 | 指向utf8常量池,表示类型 |
field_info
类型 | 名称 | 数量 | 说明 |
u2 |
access_flags | 1 | 字段修饰符 |
u2 | name_index | 1 | 字段名,指向常量池字符串项 |
u2 | descriptor_index | 1 | 字段数据类型,指向常量池字符串项 |
u2 | attributes_count | 1 | 属性个数 |
attribute_info | attributes | attributes_count | 属性 |
method_info
类型 | 名称 | 数量 | 说明 |
u2 |
access_flags | 1 | 方法修饰符 |
u2 | name_index | 1 | 方法名,指向常量池字符串项 |
u2 | descriptor_index | 1 | 方法参数和返回值类型,指向常量池字符串项 |
u2 | attributes_count | 1 | 属性个数 |
attribute_info | attributes | attributes_count | 属性 |
attribute_info
有一下几种attribute类型。
属性名称 | 使用位置 | 含义 |
code | 方法 | 字节码指令 |
ConstantValue | 字段 | final定义的常量 |
Deprecated | 类、方法、字段 | 声名位deprecated的类、字段、方法 |
Exceptions | 方法 | 方法抛出的异常 |
InnerClasses | 类 | 内部类列表 |
LineNumberTable | code | 源码行号欲指令对应关系 |
LocalVariableTable | code | 方法局部变量 |
SourceFile | 类 | 原文件名称 |
Synthetic | 类、方法、字段 | 编译器自动生成 |
code
类型 | 名称 | 数量 | 说明 |
u2 | attribute_name_index | 1 | 指向一个Code的utf8常量池 |
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 | attribute_count | 1 | 属性长度 |
attribute_info | attribute | attribute_count | 属性 |
exception_info
类型 | 名称 | 数量 | 说明 |
u2 | start_pc | 1 | 开始代码行 |
u2 | end_pc | 1 | 结束代码行 |
u2 | handler_pc | 1 | 执行代码行 |
u2 | catch_type | 1 | 异常类型 |
exception
这里的exception是和code平级的,作用是列举出方法中可能抛出的受查异常,也就是方法throws后面的异常。
类型 | 名称 | 数量 | 说明 |
u2 | attribute_name_index | 1 | 指向一个Exception的utf8常量池 |
u4 | attribute_length | 1 | 长度 |
u2 | number_of_exception | 1 | 个数 |
u2 | exception_index_table | number_of_exception | 指向class的常量池 |
LineNumberTable
描述java源码行号欲字节码行号的对应关系,抛出异常时显示行号。line_number_info包括了start_pc line_number两个u2的数据项,前者是字节码行号,后者是java源码行号。
类型 | 名称 | 数量 | 说明 |
u2 | attribute_name_index | 1 | 指向一个LineNumberTable的utf8常量池 |
u4 | attribute_length | 1 | 长度 |
u2 | number_of_table | 1 | 个数 |
line_number_info | line_number_table | number_of_table | 表 |