概要
执行引擎是java虚拟机最核心的组件之一,栈帧是用于支持虚拟机进行方法调用和方法执行的数据结构。栈帧存储了方法的局部变量表、操作数栈、冬天连接和方法返回地址等信息
局部变量表
局部变量表用于存放方法参数和内部定义的局部变量。以变量槽为基本单位。
操作数栈
java的指令集都是面向栈的,所有的指令集的参数都是要从栈中间取出值。里面存储的方法执行过程中的数据。栈内的数据必须有着严格的顺序。
动态链接
java属于动态语言,因此需要支持方法调用过程中的动态链接。
方法调用
方法调用阶段的任务就是确定被调用方法的版本。
解析
所有方法调用中的目标方法在class文件里面都市衣蛾常量池中的符号引用。有一部分会在类加载的解析阶段即可确认调用版本,而另一部分只有在运行的时候才能明确下来、
在java虚拟机提供了5条方法调用字节码指令。分别如下;
1. invokestatic:静态方法,这个属于在解析阶段即可明确调用版本的
2. invokespecical:调用实例构造器方法、私有方法、父类方法。这个同样也可以在解析阶段明确版本,同样的还有用final修饰的方法
3. invokevirtual:调用所有的虚方法.类似于重写父类的方法,这个只有在运行期才能明确调用的版本
4. invokeinterface:调用接口方法。会在运行期间再明确一个实现此接口的对象。那么invokeinterface和invokevirtual有什么区别呢?为了提高确认调用版本的性能,jvm使用了虚方法表。虚方法表存放着各个方法的实际入口。如果某个方法在子类中没有被重写,那么子类的虚方法表里面的地址入口和父类相同方法的地址入口是一致的。如果重写了,那么是子类方法的地址入口。因此对于类继承来说,无论是子类还是父类,方法在方法表中占据的位置是相同的。而对于接口实现来说,由于可以继承多个接口,因此方法在方法表中占据的位置是不同的。在确认调用版本的时候,需要根据每个实现类一一查找
5. invokedynamic:再次之前的4个调用指令,分派逻辑都封装在JVM中。而invokedynamic可以根据用户锁定的引导方法确认方法调用版本