解析调用

所有方法调用的目标方法在Class文件里边都是一个常量池中的符号引用。

在类加载的解析阶段,会将其中的一部分符号引用转化为直接引用,

这种解析能成立的前提是:方法在程序真正运行之前就有一个可确定的调用

版本,并且这个方法的调用版本在运行期是不改变的。这类方法的调用被称为

解析(Resolution)。

解析的方法

Java语言中符合“编译期可知,运行期不可变”这个要求的方法,主要有静态方法和

私有方法两大类,前者与类型直接关联,后者在外部不可被访问,这两种方法各自的

特点决定了它们都不可能通过继承或其他的方式重写出其他版本,因此适合在类加载

阶段进行解析。

调用方法的指令

调用不同的方法需要使用不同的指令。Java虚拟机支持一下指令

  • invokestatic:用于调用静态方法
  • invokespecial:用于调用实例构造器<init>()方法、私有方法和父类中的方法
  • invokevirtual:用于调用所有虚方法
  • invokeinterface:用于调用接口方法,会在运行时再确定一个实现该接口的对象。
  • invokedynamic:先在运行时动态解析出调用点限定符所引用的方法,然后再执行该方法。

非虚方法 & 虚方法

只要被invokestaticinvokespecial指令调用的方法,都可以在解析阶段中确定唯一的调用版本,

Java语言里符合这个条件的方法共有静态方法、私有方法、实例构造器、父类方法4种。再加上被

final修饰的方法(尽管它使用invokevirtual指令调用),这5中方法调用会在类加载的时候就可以

把符号引用解析为该方法的直接引用。这些方法统称为“非虚方法”(Non-Virtual Method)。

与之相反,其他的方法就被称为“虚方法”(Virtual Method)。