虚拟机字节码执行引擎
- 虚拟机执行引擎脑图:
- 执行引擎是Java虚拟机核心的组成部分之一
- 在软件层面实现,具体的指令集不受硬件层面影响
运行时栈帧结构
- JVM以方法作为最基本执行单元;而栈帧则是支持虚拟机对方法进行调用、执行的数据结构
- 栈帧包括了方法的局部变量表、操作数栈、动态链接、方法返回地址等
- 栈帧结构图:
局部变量表
- 局部变量表(Local Variables Table)是一组变量值的存储空间,用于存放方法参数和方法内部定义 的局部变量
- 变量槽是局部变量表的最小单位,变量槽支持32位的数据类型存储;而对于Long、Double(64位)的数据类型则需要2个连续变量槽
操作数栈
- 操作数栈又称操作栈,它是一个后入先出的栈.
- 操作数栈的每一个元素可以是任意的数据类型,32位数据元素占的栈容量为1,64位数据元素的栈容量位2;
动态连接
- 在类加载阶段将常量池符号引用转化为直接引用称为静态解析;另一部分符号引用在运行时转化为直接引用,称为动态连接
返回地址
- 一个方法的执行会产生两个结果,一个为正常调用完成,会产生方法返回指令,返回指令会决定返回值是否存在以及返回值的类型;一个为异常调用完成,不会提供任何返回值;
方法调用
- 一切方法调用在Class文件中都是符号引用,而不是方法在内存的实际入口;这个特性给Java赋予了极强的动态扩展能力
- 解析:在类加载的解析阶段,存在着符号引用转化成为直接引用的步骤(这只适用于对于在加载阶段可以确定的方法,如私有类、静态类);换而言之,这种方法适用于无法通过重写、其余方式转变成为其余版本
- 对于不同的解析阶段,JVM支持五种字节码指令:
- invokestatic:调用静态方法
- invokespecial:调用实例构造器()方法、私有方法和父类中的方法
- invokevirtual:于调用所有的虚方法
- invokeinterface:调用接口方法,会在运行时再确定一个实现该接口的对象
- invokedynamic:前面四条指令由JVM指定分派逻辑,这一条由用户指定分派逻辑
- 在解析阶段可以确定的方法:静态方法、私有方法、构造方法、父类方法、被final修饰的方法
- 分派
- Java三大特性继承、多态、封装;分派则是多态的基本体现
- 静态分派是指在类加载解析阶段可以确定的方法,如:重载
- 动态分派是指在运行时确定执行的方法,如:重写
- JVM中动态分派根据实际类型来决定,JVM中根据实际类型决定目标方法;
- 为了性能考虑,JVM并不会频繁的搜索实际类型元数据,优化手段是虚方法表
- 虚方法表如图:
- 虚方法表:
- 虚方法表记录了各个方法的实际入口地址
- 若子类、父类没有重写,则指向父类方法入口
- 若子类重写父类,则指向子类方法入口