02java method.invoke_Java method invoke的指令简介

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

invokestatic

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

invokevirtual

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

invokespecial

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

invokeinterface

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

操作码 操作数说明

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.

实例初始化方法(())方法

2. 私有方法

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

invokespecial and Private Methods

看下面一个例子:

Java代码 a4c26d1e5885305701be709a3d33442f.pnga4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

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();

}

}

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代码 a4c26d1e5885305701be709a3d33442f.pnga4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

0: new

#5; //class

Subclass

3:

dup

4: invokespecial

#6; //Method

"":()V

7:

astore_1

8:

aload_1

9: invokevirtual

#7; //Method

exampleMethod:()V

12:

return

0: new #5; //class Subclass

3: dup

4: invokespecial #6; //Method "":()V

7: astore_1

8: aload_1

9: invokevirtual #7; //Method exampleMethod:()V

12: return

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

Bytecode代码 a4c26d1e5885305701be709a3d33442f.pnga4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

0:

aload_0

1: invokespecial

#5; //Method

interestingMethod:()V

4:

return

0: aload_0

1: invokespecial #5; //Method interestingMethod:()V

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虚拟机》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值