一、运行时栈帧结构
1.栈帧定义:用于支持虚拟机进行方法调用和方法执行的数据结构,它是虚拟机的虚拟机栈的栈元素。存储了局部变量表、操作数栈、动态连接、方法返回地址等信息,每一方法从调用开始到执行完成的过程,对于栈帧在虚拟机中里面入栈到出栈的过程。在代码编译期,栈帧需要多大的局部变量表、多深的操作数栈都已经确定,并写入到方法表的Code中,程序运行期不会改变。
2.局部变量表
(1)局部变量表定义:是一组变量值存储空间,用于存放方法参数和方法内部定义的局部变量,编译期在方法表的Code 属性的max_locals数据项中确定了该方法局部变量表最大容量。局部变量表的容量以Slot为最小单位,一个Solt可以存放一个32位以内的数据类型,64位的数据类型(long、double)要使用两个连续的Slot存放,并且无论这两个连续的Slot是否是原子性的,都是安全的。
(2)虚拟机执行实例方法时,局部变量表中的第0位索引的Solt用于存放方法所属对象的实例(this),其余参数按照参数表顺序,从第1位开始分配。
(3)如果一个局部变量表定义了但没有赋初始值是不能使用的。
3.操作数栈
(1)操作数栈(操作栈)定义:后入先出栈,代码编译期就决定了操作数栈的最大深度并写入方法表Code 属性的max_stacks中,操作数栈中的元素可以是java中任意数据类型,32位数据类型占容量1,64位数据类型占容量2.虚拟机基于栈的执行引擎(方法中计算的入栈和出栈),其中的栈就是指操作数栈。
4.动态连接
(1)动态连接定义:程序运行期,将栈帧中包含指向运行时常量池中栈帧所属方法的引用转换为直接引用的过程被称为动态连接。
5.方法返回地址
(1)方法返回有两种方式:执行引擎遇到方法返回字节码指令;在方法执行过程中遇到异常。
二、方法调用
1.解析
(1)解析定义:在方法调用中目标方法在Class文件里面都是一个常量池的符号引用,在类加载的解析阶段,会将其中一部分符号引用转化为直接引用,这主要发生在静态方法和私有方法,这类方法调用称为解析。
(2)java虚拟机提供5条调用字节码的指令
invokestatic:调用静态方法
invokespecial:调用实例构造器方法,私有方法和父类方法
invokevirtual:调用所有虚方法
invokeinterence:调用接口方法,运行时确定实现接口对象
invokedynamic:先在运行时解析出调用点限定符所引用的方法,然后执行此方法
(3)解析调用一定是一个静态过程,编译期完全确定,在类加载的解析阶段就会把涉及的符号引用全部转变为可确定的直接引用,不会延迟到运行期完成。
2.分派
(1)静态分派
静态方法会在类加载时期酒进行解析,静态方法显然会有重载方法的,选择重载方法版本的过程是通过静态分派完成的。
(2)动态分派
在运行期根据实际类型确定方法实际执行版本的分派过程称为动态分派。
(3)单分派与多分派
方法接受者和方法的参数统称为方法的宗量,单分派是根据一个宗量对目标方法进行选择,多分派则是根据多于一个宗量对目标方法进行选择。