Java method invoke的指令简介
发布日期:2021-10-02 09:00:29 浏览次数:6 分类:技术文章

本文共 3443 字,大约阅读时间需要 11 分钟。

  • 博客分类:

方法调用相关的jvm子令集主要有一下四种:

 

invokestatic ------------------------------->调用类方法(静态绑定,速度快)

 

invokevirtual ------------------------------>调用实例方法(动态绑定)

 

invokespecial ----------------------------->调用实例方法(静态绑定,速度快)

 

invokeinterface --------------------------->调用引用类型为interface的实例方法(动态绑定)

 

invokedynamic --------------------------->JDK 7引入的,主要是为了支持动态语言的方法调用。可参考

      

 

操作码   操作数 说明

invokestatic indexbyte1,indexbyte2 把args从stack中弹出,调用constant pool索引指向的实例方法

 

invokevirtual indexbyte1,indexbyte2 把objectref和args从stack中弹出,调用constant pool索引指向的实例方法

 

invokespecial indexbyte1,indexbyte2 把objectref和args从stack中弹出,调用constant pool索引指向的实例方法

 

invokeinterface indexbyte1,indexbyte2 把objectref和args从stack中弹出,调用constant pool索引指向的实例方法

 

//-----------------------------------------------举例浅析区别----------------------------------------------------------------

invokevirtual和invokespecial的区别在于:invokespecial通常根据引用的类型选择方法,而不是对象的类来选择!即它使用静态绑定而不是动态绑定。

 

使用invokespecial指令分为下面三种情况:

1. 实例初始化方法(<init>())方法

2. 私有方法

3. 使用super关键字调用的方法

 

 

invokespecial and Private Methods

看下面一个例子:

 

Java代码  
  1. class Superclass {   
  2.     private void interestingMethod() {   
  3.         System.out.println("Superclass's interesting method.");   
  4.     }   
  5.     
  6.     void exampleMethod() {   
  7.         interestingMethod();   
  8.     }   
  9. }   
  10.   
  11. class Subclass extends Superclass {   
  12.     void interestingMethod() {   
  13.         System.out.println("Subclass's interesting method.");   
  14.     }   
  15.     
  16.     public static void main(String args[]) {   
  17.         Subclass me = new Subclass();   
  18.         me.exampleMethod();   
  19.     }   
  20. }  
class Superclass {    private void interestingMethod() {        System.out.println("Superclass's interesting method.");    }     void exampleMethod() {        interestingMethod();    }}class Subclass extends Superclass {    void interestingMethod() {        System.out.println("Subclass's interesting method.");    }     public static void main(String args[]) {        Subclass me = new Subclass();        me.exampleMethod();    }}

 

 Here are the bytecodes for the main() method of class Subclass:

Bytecode代码  
  1. 0:   new     #5; //class Subclass   
  2. 3:   dup   
  3. 4:   invokespecial   #6; //Method "<init>":()V   
  4. 7:   astore_1   
  5. 8:   aload_1   
  6. 9:   invokevirtual   #7; //Method exampleMethod:()V   
  7. 12:  return  

 Subclass从Superclass处继承了exampleMethod()方法。当Subclass的me对象调用exampleMethod()时使用的是invokevirtual。JVM会创建一个新的栈帧并将其压入栈,然后执行exampleMethod()的bytecode。下面是exampleMethod()的bytecode:

Bytecode代码  
  1. 0:   aload_0   
  2. 1:   invokespecial   #5; //Method interestingMethod:()V   
  3. 4:   return  

exampleMethod()首先将赋给局部变量0的reference压入stack(隐含参数this被传入给所有的实例方法),然后使用invokespecial指令通过这个引用调用interestingMethod()。

尽管这里的对象时Subclass的实例,而且Subclass类中的interestingMethod()方法也是能够访问的,但是JVM最终还是调用了Superclass类中的interestingMethod()方法。

程序的正确输出为:"Superclass's interesting method",因为这里生成的bytecode中调用的interestingMethod()使用的是invokespecial指令,而调用invokespecial指令时,JVM会按照你reference type来choice调用的method。

 

//-----------------------------------------------------------------指令调用和速度PK-------------------------------------------------------

可想而知,调用接口引用方法可能要比调用类引用方法慢。因为,当JVM遇到invokevirtual指令时,它把实例方法的符号引用解析为直接引用,所以生成的直接引用很可能是方法表中的一个偏移量,而且从此往后都可以使用同样的偏移量。但对于invokeinterface指令来说,虚拟机每一次遇到invokeinterface指令,都不能不重新搜寻一遍方法表,因为虚拟机不能够假设这一次的偏移量与上一次的偏移量相同。

最快的指令莫过于invokespecial和invokestatic,因为这些指令调用的都是静态绑定的,即在编译器确定了!所以当JVM为这些指令解析符号引用时,将符号引用转换成为直接饮用,所生成的直接引用将包含一个指向实际操作码的指针。

 

以上内容参考《深入Java虚拟机》

转载地址:https://blog.csdn.net/jiafu1115/article/details/7089384 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Java中的内部类和反射
下一篇:经典文章: stack 和 heap

发表评论

最新留言

很好
[***.229.124.182]2024年04月15日 04时05分51秒