方法调用与返回指令
方法调用指令
- 方法调用指令:invokevirtual、invokeinterface、invokespecial、invokestatic . invokedlynamic
以下5条指令用于方法调用:
- invokevirtual:指令用于调用对象的实例方法,根据对象的实际类型进行分派(虚方法分派),支持多态。这也是Java语言中最常见的方法分派方式。
- invokeinterface:用于调用接口方法,它会在运行时搜索由特定对象所实现的这个接口方法,并找出适合的方法进行调用。
- invokespecial:用于调用一些需要特殊处理的实例方法,包括实例初始化方法(构造器)、私有方法和父类方法。这些方法都是静态类型绑定的,不会在调用时进行动态派发。
- invokestatic:用于调用命名类中的类方法(static方法)。这是静态绑定的。
- invokedynamic:调用动态绑定的方法,这个是JDK 1.7后新加入的指令。用于在运行时动态解析出调用点限定符所引用的方法,并执行该方法。前面4条调用指令的分派逻辑都固化在java 虚拟机内部,而invokedynamic指令的分派逻辑是由用户所设定的引导方法决定的。
注意:
- invokevirtual是调用类中的非静态普通方法,而这种实例方法可能调用的是子类重写的非静态普通方法,比如A a = new B();a.hello(),其中B类继承A类,并且B类重写了A类中的hello()方法,这种情况下就是invokevirtual了,但是有可能该类没有子类,调用的就是本类中的非静态普通方法,这种情况也是invokevirtual了
- invokeinterface是对接口而言的,用属于接口类型的对象调用方法的时候就是这个
- invokespecial只有构造器、私有方法、super.方法名()调用父类方法这几种情况,其中调用父类方法这种情况可能出现其直接父类没有该方法,那就可以调用其父类继承的父类中的该方法,最终找到一个方法调用就是了
- invokestatic是调用static静态方法,无论是使用对象.静态方法名()还是类名.静态方法名()都是invokestatic,也不难理解
方法返回指令
方法调用结束前,需要进行返回。方法返回指令是根据返回值的类型区分的。
- 包括ireturn(当返回值是 boolean、byte、char、short和int类型时使用)、lreturn、freturn、dreturn和areturn
- 另外还有一条return 指令供声明为 void的方法、实例初始化方法以及类和接口的类初始化方法使用。
举例:
通过ireturn指令,将当前函数操作数栈的顶层元素弹出,并将这个元素压入调用者函数的操作数栈中(因为调用者非常关心函数的返回值),所有在当前函数操作数栈中的其他元素都会被丢弃。
如果当前返回的是synchronized方法,那么还会执行一个隐含的monitorexit指令,退出临界区。
最后,会丢弃当前方法的整个帧,恢复调用者的帧,并将控制权转交给调用者。
对应的代码:
public int methodReturn(){
int i = 500;
int j = 200;
int k = 50;
return (i +j)/ k;
}
int k = 50;
return (i +j)/ k;
}