JVM虚拟机是如何执行方法调用的

先说一下JVM虚拟机中5种方法调用字节码指令:

      invokestatic:调用静态方法

      invokespecial:调用私有实例方法、构造器,以及使用Super关键字调用父类实例方法、构造器和实现接口的默认方法

      invokevirtual:调用所有的虚方法(静态方法、私有方法、实例构造器、父类方法、final方法都是非虚方法)

      invokeinterface:调用接口方法,会在运行时期再确定一个实现此接口的对象。

      invokedynamic:现在运行时期动态解析出调用点限定符所引用的方法,然后再执行该方法,在此之前的4条指令,分派逻辑都是固化在虚拟机里面的,而invokedynamic指令的分派逻辑是由用户所设定的引导方法决定的。

     看到上述的概述:可能会有人问那Java虚拟机有没有能够直接确定目标方法的方法呢,答案是能定的,只有被final修饰的方法,才能够直接确定目标方法,这也是唯一能够直接确定目标方法的方法。

     在编译过程中,我们并不知道目标方法在内存中的具体地址值,因此Java编译器会暂时用符号引用来代替该目标方法。(符号引用表示了类名或者接口名、方法名、方法描述符。符号引用可以分为两种:接口符号引用和非接口符号引用),符号引用储存在Class文件的常量池里面。

  非接口符号引用,在Java虚拟机中是根据如下三步来查找的:

     1.先在本类中查找符合方法名、方法描述符相同的方法。

     2.如果在上一步中没有找到,就会去该类的父类中查找,直到Object类

     3.如果还是没找到,那它就会去该类间接或者直接实现的类中继续查找,但是查找的一定非私有、非静态的方法,如果查到多个符合条件的目标方法,就会随机选一个。

从上面可以看到,父类的静态方法可以被子类调用,除此之外,子类会隐藏父类同名、同描述符的静态方法。(隐藏父类的静态方法与重写不一样,这个要区分开来)

接口符号引用,在Java虚拟机中是根据如下三步来查找:

    1.先在本接口中查找符合方法名、方法描述符相同的方法。

    2..如果在上一步中没有找到,就会在Object类中的共有实例方法中查找。

   3.如果还是没找到,就会去该接口的超接口中查找,但是查找的一定非私有、非静态的方法,如果查到多个符合条件的目标方法,就会随机选一个。

在经过上述的查找后符合引用就被解析成实际引用了,对于可以静态绑定的方法而言,实际引用是一个指向方法的指针(个人理解为地址值),对于动态绑定的方法而言,实际引用则是一个方法表里面的索引(下篇会介绍什么是方法表。)

展开阅读全文

没有更多推荐了,返回首页