1、操作数栈
(1)操作数栈也被称为表达式栈
(2)操作数栈在方法执行过程中,根据字节码指令,往栈中写入数据(即压栈和弹栈)
(3)如果被调方法有返回值,其返回值将会被压入当前栈帧的操作数栈中,并更新PC寄存器中下一条指令的地址
(4)JVM的解释引擎是基于栈的执行引擎,其中的栈指的便是操作数栈
(5)操作数栈主要用于保存计算过程的中间结果,同时作为计算过程中变量临时存储空间
(6)操作数栈是JVM执行引擎的一个工作区,当一个方法开始执行时会创建对应的栈帧,这个方法的操作数栈和局部变量表此时是空的
(7)操作数栈的深度在编译器就确定好了
(8)与局部变量表相同,32位数据占1个slot,54位数据占2个slot
(9)操作数栈并非采用索引方式来访问,因为栈只有压栈和弹栈两个操作
所有的局部变量先经过操作数栈,然后弹栈进入局部变量表,不能直接进入局部变量表
(10)栈顶缓存技术:将栈顶元素全部缓存到物理CPU寄存器中,以此降低读写次数,提升效率
2、动态链接与运行时常量池
(1)每一个栈帧内部包含一个指向运行时常量池中该栈帧所属方法的引用,包含这个引用的目的是支持当前方法的代码能够实现动态链接
(2)Java源文件被编译成字节码文件时,所有的变量和方法引用都作为符号引用保存在class文件的常量池里,运行时保存在方法区内存的运行时常量池中。动态链接的作用就是为了将这些符号引用转换为直接引用
(3)字节码中的常量池对应于方法区中的常量池被称为运行时常量池
常量池存在的作用就是提供一些符号和常量,便于指令的识别;节约内存
3、方法的调用与多态
(1)JVM中将符号引用转换为直接引用的方式与方法的绑定机制相关
静态链接:目标方法在编译期可知且运行期保持不变
动态链接:被调用的方法在编译期无法确定,只能在运行期确定下来
(2)静态链接和动态链接对应的绑定机制为:早期绑定和晚期绑定
早期绑定:采静态链接方式将符号引用转换为直接引用
晚期绑定:被调用的方法在编译期无法确定,只能在程序运行期间根据实际的类型绑定线相关的方法。
(3)Java多态机制的实现依赖于动态链接和晚期绑定
(4)Java中任何普通方法都具有虚函数特征****他们相当于C++中的虚函数(C++中虚函数需要使用virtual来声明)。如果不希望某个Java方法具备虚函数特征,可以使用final关键字来修饰
虚方法与非虚方法
(1)如果方法在编译期就确定了调用版本,这个版本在运行期是不可变的,这样的方法是非虚方法
(2)静态方法、私有方法、final方法、构造器、父类方法都是非虚方法,其他方法均为虚方法
(3)虚方法与多态有关,非虚方法不能重写,因此非虚方法不存在多态。构造方法可以重载但不可以重写,因此也是非虚方法
方法重写的本质
Java中方法重写的本质为:
(1)找到操作数栈栈顶的第一个元素所执行对象的类型,记为C
(2)如果类型C中找到与常量池中的方法描述吻合简单名称都相符的方法,则进行访问权限校对,如果校对通过就返回这个方法的引用。否则返回java.lang.IllegalAccessError异常
(3)如果类型C中没找到,按照继承关系从下往上依次对C的各个父类执行步骤(2)
(4)如果最终也没能找到这个方法的的引用,就抛出java.lang.AbstractMethodError异常
虚方法表
(1)为了提高性能,JVM在方法区中建立一个虚方法表来实现(虚方法表中不存在非虚方法),使用引用来代替查找
(2)每个类都有一个虚方法表,表中存放各个方法的市集入口
(3)虚方法表在类加载的链接阶段被创建并初始化