虚拟机字节码执行引擎

概述

Java虚拟机的执行引擎:输入的时字节码文件,处理过程是字节码解析的等效过程,输出的是执行结果。

运行时栈帧结构

一个线程中的方法调用链可能工会很长,很多方法都同时处于执行状态。对于执行引擎来说,在活动过程中,只有位于栈顶的栈帧才是有效的,称为当前栈帧,于这个栈帧相关联的方法称为当前方法。执行引擎运行的所有字节码指令都只针对当前栈帧进行操作。

接下来详细的解释一下栈帧中的局部变量表,操作数栈,动态连接,方法返回地址等各个部分的作用和数据结构。

1 局部变量表

局部变量表是一组变量值储存空间,用于存放方法参数和方法内定义的局部变量,在java编译成Class文件时,就在方法的Code属性的max_locals数据项中确立了该方法所需要分配的局部变量表的最大容量。

局部变量表的容量以变量褿(Slot)为最小单位,每一个Slot都应该能存放一个boolean,byte,char,short,int,float,reference或者returnAddress类型的数据。

在方法执行时,虚拟机使用局部变量表完成参数值到参数变量列表的传递过程的。,如果执行的是实例方法(非static的),那局部变量表的第0位索引的Slot默认的是用于传递方法所属对象实例的引用,在方法中可以通过关键字this来访问到这个隐含的参数。

2 操作数栈

操作数栈是一个先进后出的栈,同局部变量表一样,操作数栈的最大深度也在编译的时候就写到Code属性的max_stacks数据项中。当一个方法刚刚开始执行的时候,这个方法的操作数栈是空的,在方法执行的过程中,会有各种字节码指令往操作数栈中写入和提取内容,也就是出栈和入栈操作。

大多数虚拟机都会对局部变量表做一些优化处理,让下面栈帧的部分操作数栈与上面的栈帧的部分的局部变量表重叠在一起,这样就可共公用一部分数据。

3 动态连接

每一个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持在方法调用过程中的动态连接。(没有理解到)

4 方法返回地址

当方法开始执行后,只有2中方法可以退出这个方法。

1. 正常完成出口:是执行引擎遇到任意一个方法返回的字节码指令,这时候可能会有返回值传递给上层的方法调用者(调用当前方法的方法称为调用者)。

2.异常完成出口: 在方法执行过程中遇到了异常,并且这个异常没有在方法体内得到处理,无论是Java虚拟机内部产生的异常,还是使用athrow字节码指令产生的异常,只要在本方法的异常表中没有搜索到匹配的异常处理器,就会导致方法退出。

无论采用哪种退出方式,在方法推出后,都需要返回方法被调用的位置,程序才能继续执行。一般来说方法正常退出时,调用者的PC计数器的值可以作为返回地址。方法异常退出时,返回地址时通过异常处理表来确定的。

参考书籍:《深入理解java虚拟机》