背景
之前看jvm指令的时候,看到各种invokexxx指令,没区分清楚到底什么区别,正好看《深入分析java web技术内幕》这本书,里面也讲到了这部分,正好回顾并整理一下。
5种方法调用指令
一共有5种方法调用指令。
invokestatic:调用静态方法
invokespecial:调用<init>方法、private方法、super方法
invokevirtual:调用虚方法
invokeinterface:调用接口方法
invokedynamic:动态调用方法,这是java8为支持lambda表达式增加的指令
其实这里边只有两个不好理解,一个是invokevirtual,一个是invokedynamic。
invokevirtual
invokevirtual,根据名字就知道是调用虚方法,那什么是虚方法呢?
能在编译期就确定的方法是非虚方法,比如静态方法、private方法、final方法、实例构造器、父类方法(super)都是非虚方法。除此之外的方法都是虚方法。
虚方法的特点是无法在编译期确定,需要在运行时才能够确定。因为java支持多态。
那么就很好理解了,接口方法虽然也是虚方法,但是有专门的指令了,lambda表达式支持的动态方法也有专门的指令了。除此之外的虚方法都由invokevirtual调用,代表这些方法可能在运行的时候执行的是子类方法,比如所以public方法、protect方法都是要用invokevirtual来调用的。
final public方法其实也是用invokevirtual方法调用,即便它是虚方法。至于原因,参考https://www.zhihu.com/question/45131640
invokedynamic
java想要支持动态类型,加入lambda表达式,于是引入了invokedynamic指令。具体还没研究。
参考文章
22.5种方法调用指令-invokestatic,invokespecial,invokevirtual,invokeinterface,invokedynamic