二、虚拟机字节码执行引擎
1.概述
执行引擎是java虚拟机最核心的组成部分之一。执行引擎在执行代码的时候可能有解释执行(通过解释器执行),也可能有编译执行(通过即时编译器执行),当然也可能两者兼备,甚至还包含几个不同级别的编译器执行引擎,
2.运行时栈帧结构
栈帧是用于支持虚拟机进行方法调用和方法执行的数据结构,它是虚拟机运行时数据区中的虚拟机栈的栈元素,栈帧存储了方法的局部变量表、操作数栈、动态链接和方法返回地址等信息。
2.1 局部变量表
局部变量表的容量一变量槽Slot为最小单位。一个变量槽可以存放一个32位以内的数据类型,对于大于32位的类型(也就是doble和long),一般虚拟机会以高位在前的方式为其分配两个连续的slot空间。
2.2 操作数栈
操作数栈也就是操作栈,是一个先入后出的栈。当一个方法刚刚开始运行的时候,这个方法的操作数栈是空的,在方法的执行过程中,会有各种字节码指向操作数栈中写入和提取内容,也就是入栈出栈操作。
2.3 动态连接
每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态连接。Class文件中存有大量的符号引用,在接吗中的方法调用指令就以常量池中指向方法的符号引用位参数,这些符号引用一部分会在类加载阶段或第一次使用的时候转化位直接引用,这种转化称为动态解析,另外一部分将在每一个的运行期间转化为直接引用,这部分称为动态连接。
2.4 方法返回地址
当一个方法被执行后,会有两种方式退出这个方法。
- 执行引擎遇到任何一个方法返回的字节码指令,这时候可能会有返回值传递给上层的方法调用者,是否有返回值和返回值的类型将根据遇到何种方法返回指令来决定,这种退出方法的方式称为正常完成出口。
- 另外一种退出方式就是在方法执行过程种遇到了异常,并且这个异常没有在方法体内得到处理,无论是java虚拟机内部产生的异常,当时代码种使用字节码指令产生的异常,只要在本方法的异常表种没有搜索到匹配的异常处理器,就会导致方法退出,这种退出方法的方式称为异常完成出口。一个方法使用异常完成出口的方式退出,是不会给它的上层调用者产生任何返回值的。
无论用哪种退出方式,在方法退出之后,都需要返回到方法被调用的位置,程序才能继续执行,方法返回时可能训词在栈帧种保存一些信息,用来帮助恢复它的上层方法的执行状态。
方法退出的过程实际上等同于把当前栈帧出栈,因此退出时可能执行的操作有:恢复上层方法的局部变量表和操作数栈,如果有返回值的话,把返回值压入调用者栈帧的操作数栈种,调整PC计数器的值以指向方法调用指令后面的一条指令等。
2.5 附加信息
还有其他类似于调试相关的信息,这部分信息完全取决于具体的虚拟机实现。在实际开发中,一般会把动态链接、方法返回地址与其他附加信息全部归为一类,称为栈帧信息。