方法调用

JVM 字节码中,共有五种指令来实现方法的调用:

  1. invokevirtual 为最常见的情况,用于调用所有的虚方法
  2. invokespecial 是作为对 private 和构造方法 <init>() 的调用,以及父类中的方法的 调用
  3. invokeinterface 的实现跟 invokevirtual 类似,用于调用接口方法,会在运行时再确 定一个实现该接口的对象
  4. invokestatic 是对静态方法的调用
  5. invokedynamic 先在运行时动态解析出调用点限定符所引用的方法,然后再执行该方法

解析调用

使用 invokestaic 和 invokespecial 指令调用的方法,都是可以在 class 文件的解析阶段中 确定唯一的调用版本,java 语言中符合这种条件的方法一共有四种,包括静态方法,私有 方法,实例方法,父类方法。非此四类方法会存在多态的情况,因此无法在解析阶段就确定 方法的唯一调用版本

除了被 invokestatic 和 invokespecial 指令调用的方法外,还有被 final 修饰的方法,因为其 无法被继承,所以也可以被解析调用。 但是 final 方法是使用 invokevirtual 指令进行调用的

解析调用是一个静态的过程,在编译期间就可以完全确定,在类加载的阶段会把涉及到的符 号引用完全转换为明确的直接引用,无需延迟到运行期间进行动态处理