非虚方法:
如果方法在编译期就确定了具体的调用版本,这个版本在运行时是不可变的,这样的方法称为非虚方法;
静态方法、私有方法、final方法、实例构造器、父类方法都是非虚方法;
虚方法:
不是非虚方法的方法,都是虚方法;
调用指令:
虚拟机中提供了以下几条方法调用指令:
普通调用指令:
1、invokestatic:调用静态方法,解析阶段确定唯一方法版本;
2、invokespecial:调用<init>方法、私有及父类方法,解析阶段确定唯一方法版本;
3、invokevirtual:调用所有虚方法;
4、invokeinterface:调用接口方法;
动态调用指令:
5、invokedynamic:动态解析出需要调用的方法,然后执行;
前4条指令固化在虚拟机内部,方法的调用执行不可人为干预,而invokedynamic命令则支持由用户确定方法版本。其中invoke static和invokespecial指令调用的方法称为非虚方法,其余的(final修饰的除外)称为虚方法。
- JVM字节码指令集一直比较稳定,一直到Java7中才增加了一个invokedynamic指令,这是Java为了实现【动态类型语言】支持而做的一种改进。
- 但是在Java7中并没有提供直接生成invokedynamic指令的方法,需要借助ASM这种底层字节码工具来产生invokedynamic指令。直到Java8的Lambda表达式的出现,invokedynamic指令的生成,在Java中才有了直接的生成方式;
- Java7中增加的动态语言类型支持的本质是对Java虚拟机规范的修改,而不是对Java语言规则的修改,这一块相对来讲比较复杂,增加了虚拟机中方法的调用。最直接的受益者就是运行在Java平台的动态语言的编译期。