尚硅谷2020最新版宋红康JVM教程-中篇-第2章Class文件结构-6-方法调用与返回指令

    科技2022-07-12  142

    引言

    方法调用指令

    方法调用指令:invokevirtual、invokeinterface、invokespecial、invokestatic、invokedynamic以下5条指令用于方法调用:

    invokevirtual指令用于调用对象的实例方法,根据对象的实际类型进行分派(虚方法分派),支持多态。这也是Java语言中最常见的方法分派方式。invokeinterface指令用于调用接口方法,它会在运行时搜索由特定对象所实现的这个接口方法,并找出适合的方法进行调用。invokespecial指令用于调用一些需要特殊处理的实例方法,包括实例初始化方法(构造器)、私有方法和父类方法。这些方法都是静态类型绑定的,不会在调用时进行动态派发。invokestatic指令用于调用命名类中的类方法(static方法)。这是静态绑定的。invokedynamic:调用动态绑定的方法,这个是JDK1.7后新加入的指令。用于在运行时动态解析出调用点限定符所引用的方法,并执行该方法。前面4条调用指令的分派逻辑都固化在java虚拟机内部,而invokedynamic指令的分派逻辑是由用户所设定的引导方法决定的。

    invokespecial 和invokestatic 都不可能重写

    代码举例

    package T1; import java.util.Date; public class MethodInvokeReturnTest { //方法调用指令:invokespecial public void invokel() { //情况1:类实例构造器方法:<init>() Date date = new Date(); Thread t1 = new Thread(); //情况2:父类的方法 super.toString(); //情况3:私有方法 methodPrivate(); // 0 new #2 <java/util/Date> // 3 dup // 4 invokespecial #3 <java/util/Date.<init>> // 7 astore_1 // 8 new #4 <java/lang/Thread> //11 dup //12 invokespecial #5 <java/lang/Thread.<init>> //15 astore_2 //16 aload_0 //17 invokespecial #6 <java/lang/Object.toString> //20 pop //21 aload_0 //22 invokespecial #7 <T1/MethodInvokeReturnTest.methodPrivate> //25 return } private void methodPrivate() { } //方法调用指令:invokestatic public void invoke2() { methodstatic(); //0 invokestatic #8 <T1/MethodInvokeReturnTest.methodstatic> //3 return } private static void methodstatic() { } //方法调用指令:invokeinterface public void invoke3() { Thread t1 = new Thread(); ((Runnable) t1).run(); // invokeinterface #9 <java/lang/Runnable.run> count 1 Comparable<Integer> com = null; com.compareTo(123); // invokeinterface #11 <java/lang/Comparable.compareTo> count 2 } } package T1; public class InterfaceMethodTest { public static void main(String[] args) { AA bb = new BB(); // invokespecial #3 <T1/BB.<init>> bb.method2(); // invokeinterface #4 <T1/AA.method2> AA.method1(); // invokestatic #5 <T1/AA.method1> } } interface AA { public static void method1() { } public default void method2() { } } class BB implements AA { }

    方法返回指令

    方法调用结束前,需要进行返回。方法返回指令是根据返回值的类型区分的。 包括ireturn(当返回值是boolean、byte、char、short和int 类型时使用)、lreturn、freturn、dreturn和areturn另外还有一条return 指令供声明为void的方法、实例初始化方法以及类和接口的类初始化方法使用。

    举例: 通过ireturn指令,将当前函数操作数栈的顶层元素弹出,并将这个元素压入调用者函数的操作数栈中(因为调用者非常关心函数的返回值),所有在当前函数操作数栈中的其他元素都会被丢弃。如果当前返回的是synchronized方法,那么还会执行一个隐含的monitorexit指令,退出临界区。最后,会丢弃当前方法的整个帧,恢复调用者的帧,并将控制权转交给调用者。

    代码举例

    public class MethodReturnTest { public float returnFloat() { int i = 10; return i; // 0 bipush 10 //2 istore_1 //3 iload_1 //4 i2f //5 freturn } }
    Processed: 0.010, SQL: 8