java里的五大invoke指令分别是invokespecial、invokevirtual、invokestatic、invokeinterface、invokedynamic。
静态方法的调用,生成的是invokestatic指令。
接口方法的调用,生成的是invokeinterface指令。
其他的方法,区别在于非final的方法生成invokevirtual指令,这是java保证多态的关键。final方法则生成invokespecial指令。
最复杂的当属于invokedynamic指令了,其目的是实现动态类型。众所周知,java是一种动态类型语言。举个例子,python可以这样写代码:
class A:
def print(self):
print('A')
class B:
def print(self):
print('B')
if __name__ == '__main__':
# 取命令行参数
print(A())
print(B())
如果换成java,这两个类就必须实现同一个接口。但是现在java也可以了。lambda表达式就是这种代码。这个指令底层依靠methodhandle来实现,其实现原理超级复杂。但简而言之,就是把callsite传给invokedynamic指令,从call site中找到bootstrap method来调用真正的方法。