执行子系统就是执行Class文件代码的子系统,Hotspot的实现中包含了解释执行和编译执行两种方式
编译执行
编译过程是根据即时编译器产生的本地代码执行的过程
Java 虚拟机栈
Java虚拟机栈是实现方法调用和方法执行的关键,栈以FILO的形式操作,方法调用的时候入栈,调用结束之后弹出
局部变量表
该区域保存方法内的局部变量,包含方法参数
如果是非静态方法,该区域首个为this指针,指向当前的实例对象
!这里也能看出来 this 关键字的原理,是在方法调用的时候在局部变量表中填充的一个变量
局部变量表以 Solt 为单位分配内存,double 和 long 可能需要两个 Solt
另外这里也是 GC ROOT 的目标之一,在战帧 - 局部变量表的对象肯定都是当前存活的对象
方法返回地址
就是调用方法的地方,退出方法的方式有异常和正常返回两种,都需要返回到方法调用时的执行点继续执行
操作数栈
Java的解释执行引擎的主要工作区,以LIFO的形式操作
例如在执行加法运算的时候会先将两个操作数入栈,然后调用加法的字节码指令出栈并相加,入栈结果,或继续赋值给变量
动态链接
Java 支持动态语音特性,可能只有在运行期才能知道方法调用的真实目标方法是,所以此时只能保存符号引用
方法调用
Class 文件中所有的方法名都会保存在Class 文件常量池,一些可以在编译期就确定的方法会在转为Class文件时就转化为直接引用,这个就是静态解析,而动态解析的则是在编译期无法确定的方法
Java的方法调用支持重写和重载
重载
重名的方法只有参数列表不一样
返回值不一样无法区分两个方法
重写的实现
重写方法的调用实现基于动态单分派,属于动态解析的一种,对应的字节码指令为 invokevirtual
动态分派
方法只有在执行期间才能确定调用目标,实际中会在方法调用时候获取方法栈帧的第一个参数(this)的实际类型,而不同的调用可能会有不同的实际类型,所以调用的方法也会不同,如果当前方法没有则会往父类对象继续调用
虚方法表
JVM 会在方法执行的时候确定实际的方法地址,如果每次在动态分派的时候都需要上搜索类的元数据就很麻烦,所以建立了虚方法表
每个类在初始化的时候就创建了虚方法表,该表包括了所有该类的方法,包括从父类继承的
重载的实现
重载方法基于静态多分派,属于静态解析的一种
静态分派
JVM的静态分派实现是根据方法参数列表来的,并且是根据参数的静态类型而非实际类型
多分派
根据方法的参数列表进行匹配,多个方法参数就表示多个宗量,所以是多分派