JVM方法寻址

442 阅读2分钟

1、重载(静态绑定)

类名、方法名以及方法描述符(method descriptor)形成重载。

方法描述符:参数类型,返回类型(JVM独有)。

2、重写(动态绑定)

当子类和父类中方法名和方法描述符都一致形成重写。

重写在jvm识别方法时无法直接识别,要根据调用者的类型。

3、寻找方法

public static void main(String[] args) {    
    try {       
     C c = () -> true;        A a = new B();     
     double price = a.discountedPrice(5.0, c);
     System.out.println("price:" + price);    
       }catch (Exception e){  
   }
}

public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: invokedynamic #2,  0              // InvokeDynamic #0:isVIP:()LC;
       5: astore_1
       6: new           #3                  // class B
       9: dup
      10: invokespecial #4                  // Method B."<init>":()V
      13: astore_2
      14: aload_2
      15: ldc2_w        #5                  // double 5.0d
      18: aload_1
      19: invokevirtual #7                  // Method A.discountedPrice:(DLC;)D
      22: dstore_3
      23: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
      26: new           #9                  // class java/lang/StringBuilder
      29: dup
      30: invokespecial #10                 // Method java/lang/StringBuilder."<init>":()V
      33: ldc           #11                 // String price:
      35: invokevirtual #12                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      38: dload_3
      39: invokevirtual #13                 // Method java/lang/StringBuilder.append:(D)Ljava/lang/StringBuilder;
      42: invokevirtual #14                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      45: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      48: return
}

执行 a.discountedPrice(5.0, c),寻址步骤,如图:

方法表

类加载的准备阶段构造与该类相关联的方法表。分为两种虚方法表(对应invokevirtual指令),接口方法表(对应invokeinterface指令)

方法表本质上是一个数组,每个数组元素指向一个当前类及其祖先类中非私有的实例方法。

这些方法可能是具体的、可执行的方法,也可能是没有相应字节码的抽象方法。

方法表满足两个特质:其一,子类方法表中包含父类方法表中的所有方法;其二,子类方法在方法表中的索引值,与它所重写的父类方法的索引值相同

内联缓存

内联缓存是一种加快动态绑定的优化技术。

它能够缓存虚方法调用中调用者的动态类型,以及该类型所对应的目标方法。

在之后的执行过程中,如果碰到已缓存的类型,内联缓存便会直接调用该类型所对应的目标方法。

如果没有碰到已缓存的类型,内联缓存则会退化至使用基于方法表的动态绑定。