一、运行时栈帧结构
栈帧是用于支持虚拟机方法调用和方法执行的结构,栈帧存储了方法的局部变量表,操作数栈,动态链接,方法返回地址等信息。每一个方法从调用开始到执行完成的过程,都对应一个栈帧在虚拟机栈从入栈到出栈的过程。在编译程序代码的时候,栈帧需要分配多大内存已经确定。
局部变量表:用于存放方法参数和和方法内部定义的局部变量。
操作数栈:
动态链接:每个栈帧都包含一个指向运行时常量池中该栈帧所属的方法引用,持有这个方法引用是为了调用过程中的动态链接。我们知道常量池中有大量的符号引用,字节码中的方法调用指令,就以常量池中指向方法的符号引用作为参数,这些符号引用部分会在类加载或者第一次使用时就转化为直接引用,这种转化称为静态分析,另外一部分将在每次运行期间转化为直接引用,这部分称为动态链接。
方法返回地址:方法退出有两种方式,执行引擎遇到任何一个方法返回的字节码指令,正常退出,也可能遇到异常退出。
二、方法调用
解析
方法在程序真正运行之前就有一个确定的版本,并且这个方法的调用版本在运行期不可变的,调用目标在程序写好,编译器在进行编译时就必须确定下来,这类方法称为解析。这类方法包括静态方法和私有方法,实例构造器,父类方法,前者直接与类型连续,后者外部不可访问,它们在加载的时候就把符号引用转为直接引用,这些方法称为非虚方法
分派
调用可能是静态的也可能是动态的。
静态分派:重载时使用哪个版本,完全取决于传入的参数和 数据类型,虚拟机在重载时通过参数的静态类型而不是实际类型作为判定依据。并且静态类型在编译期可知的,所以更具静态类型决定使用哪个重载版本。
动态分派:重写(Overide)的体现。在运行期间根据实际类型确定方法的执行版本的分派过程称为动态分派。
三、基于栈的字节码解释执行引擎
1、基于栈的指令集和基于寄存器的指令集
基于栈的指令集:依赖于操作数进行操作,优点可移植,代码相对紧凑,编译实现更加简单,缺点:执行速度相对慢一些,指令数量相同功能较多,访问内存频繁,栈顶缓存,常用操作映射的寄存器。
寄存器指令集:寄存器由硬件提供,程序直接依赖这些硬件寄存器不可避免地受到硬件的约束。
2、基于栈的解释器执行过程