虚拟机字节码执行引擎
虚拟机字节码执行引擎
1 概述
在不同的虚拟机实现里面,执行引擎在执行java代码的时候可能有解释执行和编译执行两种选择,也可能两者兼备,甚至还可能包含几个不同级别的编译器执行引擎,但是从外观上看起来,所有的java虚拟机的执行引擎都是一致的:输入的是字节码文件,处理过程是字节码解析的等效过程,输出的是执行结果。本章将主要从概念模型的角度来讲解虚拟机的方法调用和字节码执行
2 运行时栈帧结构
1)局部变量表
局部变量表是一组变量值存储空间,用于存放方法参数和方法内部定义的局部变量。在java程序被编译为class文件时,就在方法的code属性的max_locals数据项中确定了方法所需要分配的最大局部变量表的容量。
局部变量表的容量以变量槽(Variable Slot)为最小单位。
2) 操作数栈
注:
3)动态连接
4)方法返回地址
5)附加信息
3 方法调用
class文件的编译过程中不包含传统编译中的连接步骤,一切方法调用在class文件里面存储的都只是符号引用,而不是方法在实际运行时内存布局中的入口地址(相当于之前说的直接引用)。这个特性给java带来了更强大的动态扩展能力,但也使得java方法的调用过程变得相对复杂起来,需要在类加载期间甚至到运行期间才能确定目标方法的直接引用。
1)解析
在类加载阶段进行解析的情况:调用目标在程序代码写好、编译器进行编译时就必须确定下来。
2)分派
分派调用过程将会揭示多态性特征的一些最基本的体现(如重载,重写等等)。
- 静态分派
例子如下:
虚拟机在重载时是通过参数的静态类型而不是实际类型作为判定依据的。
注:重载会查找更合适的版本;
- 动态分派
它和多态性的另外一个重要体现—重写(override)有着很密切的关联。
找到主动发起调用的类是子类还是父类。
因为调用目标(个人认为就是主动发起调用的类)不确定,从子类一层层向上找方法。
3)单分派与多分派
方法的接收者与方法的参数统称为方法的宗量。单分派是根据一个宗量对目标方法进行选择,多分派则是根据多于一个的宗量对目标方法进行选择。
个人理解:
静态分派选好参数类型合适的方法,选好主动发起调用的类为基类;
动态分派:选好主动发起调用的类是基类还是子类;
注:虚拟机动态分派的实现:
4 基于栈的字节码解释执行引擎
和汇编的理解方式类似,不再赘述。