JVM解析字节码文件过程
字节码中的数据结构
field_info
在Java字节码中,field_info结构是用来描述类或接口中的字段(成员变量的)。每个field_info结构对应类文件中的一个字段。其中它的组成部分包括如下:
1.access_flags:访问标志,表示字段的访问级别(如public, private, protected, static等)和其他属性(如final volatile等)
2.name_index:字段名的索引,它是一个指向常量池的索引,常量池中的对应条目包含字段的名称
3.descriptor_index:字段描述符的索引,它也是指向常量池的索引,描述符用来表示字段的类型(如int,float, java.lang.String等)
4.attribute_count:属性数量,表示接下来跟随的属性表中的属性数量。
5.attributes:属性表,包含了对字段的额外描述信息,如常量值(ConstantValue)、字段签名(Signature)、Synthetic标记等。
例如,有这样一个类文件,代码如下:
java
public class MyClass {
private int myField;
}
对应的field_info结构将包含如下信息:
- 1.access_flags:表示private访问权限
- 2.name_index:指向常量池中包含myField字符串的条目
- 3.descritptor_index:指向常量池中包含"I"(表示Int类型)的条目
- 4.attributes_count:通常为0,除非字段有额外的属性,如ConstantValue
method_info、Code_attribute
在Java字节码中,method_info结构用于描述类或接口中的方法。每个method_info结构对应类文件中的一个方法。以下是method_info结构的组成部分:
- 1.acess_flags:访问标志,表示方法的访问级别(如public,private,protected, static等)和其他属性(如abstract. final,synchronized,native,strictfp等)
- 2.name_index:方法名的索引,这是一个指向常量池的索引,常量池中的对应条目包含方法的蒙城
- 3.descriptor_index:方法描述符的索引,这也是一个指向常量池中的索引,描述符用来表示方法的参数类型、返回值类型以及可能抛出的异常类型
- 4.attributes_count:属性数量,表示接下来跟随的属性表中的属性数量
- 5.attributes:属性表,包含了对方法的额外描述信息,如方法的代码(Code)、异常表(Exceptions)、方法签名(Signature)、注解(Annotation)等
例如,有这样一个类文件,代码如下:
java
public class MyClass {
public void myMethod(int param) {
// Method body ...
}
}
对应的method_info结构将包含以下信息:
- 1.access_flags:表示public访问权限
- 2.name_index:指向常量池中包含myMethod字符串的条目
- 3.descriptor_index:指向常量池中包含(I)V(表示一个int参数且没有返回值)的条目
- 4.attributes_count:通常至少为1,因为大多数方法都会有一个Code属性,它包含方法的字节码指令
Code属性是method_info结构中最常见的属性,它包含以下字段:
- 1.max_stack:操作数栈的最大深度
- 2.max_locals:局部变量表所需的存储空间,单位是槽位(slot),每个槽位可以存储一个32位的数据类型
- 3.code_length:字节码指令的数量
- 4.code:实际的方法字节码指令序列
- 5.exception_table_length:异常表中的条目数量
- 6.exception_table:异常处理的信息
- 7.exception_table:异常处理的信息
- 8.attributes_count:Code属性中的属性数量
- 9.attributes:Code属性中的属性表
LineNumberTable和Code结构之间的关系是什么?
LineNumberTable是Code属性中的一个可选属性,它提供了源代码行号与字节码指令之间的映射关系。这样,当异常被抛出或者在调试程序时,可以更准确地定位到源代码中的具体行。
- 1.Code属性时method_info结构中的一个属性,它包含了方法的实际字节码指令、局部变量表大小、操作数栈大小等信息
- 2.LineNumberTable属性:是Code属性中的一个可选属性,它位于Code属性的attributes数组中,如果存在,它允许调试器和其他工具将执行的字节码指令与源代码中的行号关联起来
LocalVariableTable是Code属性中的一个可选属性,它提供了方法执行期间局部变量与局部变量表槽位之间的关系。这个映射允许调试器和其他工具在运行时查看和修改变量的值,并且可以用于在异常堆栈跟踪中显示变量名
- 1.Code属性:code属性包含方法的字节码指令、局部变量表大小、操作数栈等信息。它还包含一个属性表attributes,可以包含多个属性,比如LineNumberTalbe、LocalVariableTable等
- 2.LocalVariableTable属性:LocalVariableTable是Code属性中的一个属性,位于attributes数组中。如果存在,它描述了方法中的每个局部变量及其在局部变量表中的位置、生命周期和类型
- 3.LocalVariableTable中的每个条目都描述了一个局部变量,包括它的名字、类型、在局部变量表中的槽位索引以及它在字节码中的上明周期(开始和结束的偏移量)
- 4.LocalVariableTable提供了调试器在执行期间识别和访问局部变量的能力,这对于断点调试和异常堆栈跟踪非常有用
- 5.在编译时,编译器可以选择生成或不生成LocalVariableTable。如果生成了这个表,它会使得调试更加方便,但如果为了减小类文件大小或出于其他原因,这个表可能会被忽略