在JVM中,将符号引用转换为调用方法的直接引用与方法的绑定机制相关
当一个字节码文件被装载进JVM内部时,如果被调用的目标方法在编译期确定,且运行期保持不变时,这种情况下将调用方法的符号引用转换为直接引用的过程称之为静态链接
如果被调用的方法在编译期无法被确定下来,也就是说,只能够在程序运行期将调用的方法的符号转换为直接引用,由于这种引用转换过程具备动态性,因此也被称之为动态链接。
静态链接和动态链接对应的方法的绑定机制为:早期绑定(Early Binding)和晚期绑定(Late Binding)。绑定是一个字段、方法或者类在符号引用被替换为直接引用的过程,这仅仅发生一次。
早期绑定就是指被调用的目标方法如果在编译期可知,且运行期保持不变时,即可将这个方法与所属的类型进行绑定,这样一来,由于明确了被调用的目标方法究竟是哪一个,因此也就可以使用静态链接的方式将符号引用转换为直接引用。
如果被调用的方法在编译期无法被确定下来,只能够在程序运行期根据实际的类型绑定相关的方法,这种绑定方式也就被称之为晚期绑定。
随着高级语言的横空出世,类似于Java一样的基于面向对象的编程语言如今越来越多,尽管这类编程语言在语法风格上存在一定的差别,但是它们彼此之间始终保持着一个共性,那就是都支持封装、继承和多态等面向对象特性,既然这一类的编程语言具备多态特性,那么自然也就具备早期绑定和晚期绑定两种绑定方式。
Java中任何一个普通的方法其实都具备虚函数的特征,它们相当于C++语言中的虚函数(C++中则需要使用关键字virtual来显式定义)。如果在Java程序中不希望某个方法拥有虚函数的特征时,则可以使用关键字final来标记这个方法。
如果方法在编译期就确定了具体的调用版本,这个版本在运行时是不可变的。这样的方法称为非虚方法。
静态方法、私有方法、final 方法、实例构造器、父类方法都是非虚方法。
其他方法称为虚方法。
虚拟机中调用方法的指令
普通调用指令:
动态调用指令
区别
内联缓存是一种加快动态绑定的优化技术。它能够缓存虚方法调用中调用者的动态类型,以及该类型所对应的目标方法。后续执行中,优先使用缓存,没有缓存则使用方发表。
多态优化相关的的术语:
1、单态(monomorphic):指的是仅有一种状态的情况。
2、多态(polymorphic):指的是有限数量种状态的情况,二态是多态的一种。
3、超多态(megamorphic):指的是更多种状态的情况。通常用某个阈值来区分多态和超多态。
所以,内联缓存也有对应的单态内联缓存、多态内联缓存、超多态内联缓存。
单态内联缓存:即只缓存了一种动态类型及所对应的目标方法。他的实现比较简单,即比较所缓存的动态类型,如果命令则直接调用对应的目标方法。
多态内联缓存:则缓存了多个动态类型及所对应的目标方法。它的实现需要逐个将所缓存的动态类型与当前动态类型进行比较,如果命中,则调用所对应的动态方法。