JVM——(23)字节码指令集与解析五(方法调用指令与方法返回指令)

本文探讨了JVM中各种方法调用指令(invokevirtual、invokeinterface、invokespecial、invokestatic和invokedynamic)的工作原理,通过示例代码展示了它们的区别,并剖析了方法返回指令(ireturn、freturn、dreturn、areturn)及其在实际代码中的应用。跟随实例一步步揭示虚拟机内部的执行机制。

往期文章

JVM——(1)为什么学习虚拟机
JVM——(2)聊聊JVM虚拟机
JVM——(3)类加载子系统
JVM——(4)运行时数据区的概述与程序计数器(PC寄存器)
JVM——(5)运行时数据区的虚拟机栈
JVM——(6)运行时数据区的本地方法栈
JVM——(7)运行时数据区的堆空间
JVM——(8)运行时数据区的方法区
JVM——(9)对象的实例化与访问定位
JVM——(10)执行引擎
JVM——(11)String Table(字符串常量池)
JVM——(12)垃圾回收概述
JVM——(13)垃圾回收相关算法
JVM——(14)垃圾回收相关概念的概述
JVM——(15)垃圾回收器详细篇
JVM——(16)Class文件结构一(描述介绍)
JVM——(17)Class文件结构二(解读字节码)
JVM——(18)Class文件结构三(JAVAP指令)
JVM——(19)字节码指令集与解析一(局部变量压栈、常量变量压栈、出栈局部变量表指令)
JVM——(20)字节码指令集与解析二(算数指令)
JVM——(21)字节码指令集与解析三(类型转换指令)
JVM——(22)字节码指令集与解析四(对象创建与访问指令)
JVM——(23)字节码指令集与解析五(方法调用指令与方法返回指令)
JVM——(24)字节码指令集与解析六(操作数栈管理指令)

一、方法调用指令说明


简要介绍方法调用指令:

invokevirtual、invokeinterface、invokespecial、invokestatic、invokedynamic

简要方法调用介绍

invokevirtual指令

用于调用对象的实例方法,根据对象的实际类型进行分派(虚方法分派),支持多态。

这也是Java语言中最常见的方法分派方式。

invokeinterface指令

用于调用接口方法,它会在运行时搜索由特定对象所实现的这个接口方法,并找出适合的方法进行调用。

invokespecial指令

用于调用一些需要特殊处理的实例方法,包括实例初始化方法(构造器)、私有方法和父类方法。这些方法都是静态类型绑定的,不会在调用时进行动态派发。

invokestatic指令

用于调用命名类中的类方法(static方法)。这是静态绑定的。

invokedynamic指令

调用动态绑定的方法,这个是JDK 1.7后新加入的指令。

用于在运行时动态解析出调用点限定符所引用的方法,并执行该方法。前面4条调用指令的分派逻辑都固化在java虚拟机内部,而invokedynamic指令的分派逻辑是由用户所设定的引导方法决定的。

二、通过示例代码来体会方法调用指令


接下来我们通过示例代码拉体会对应的方法指令,看看会有什么不一样?

public class MethodInvokeReturnTest {
    
    //方法调用指令:invokespecial
    public void invoke1(){
    
        //情况1:类实例的构造器方法:<init>()
        Date date = new Date();
        Thread t1 = new Thread();
        
        //情况2:父类的方法
        super.toString();
        
        //情况3:私有方法
        methodPrivate();
    }
    
    private void methodPrivate(){
    
    }
}

接下来我们把当前的代码编译一下,看看具体的字节码是怎么描述当前方法的?
在这里插入图片描述

假如我们将当前私有方法methodPrivate改为public修饰的方法就会发生改变(可重写)
在这里插入图片描述

接下来我们通过示例代码拉体会下一个方法指令,看看会有什么不一样?

public class MethodInvokeReturnTest {
    
    //方法调用指令:invokestatic
    public void invoke2(){
        methodstatic();
    }
    
    public static void methodStatic(){
    
    }
}

把当前的代码编译一下,看看具体的字节码是怎么描述当前方法的?
在这里插入图片描述

接下来我们通过示例代码拉体会下一个方法指令,看看会有什么不一样?

public class MethodInvokeReturnTest {
    
    //方法调用指令:invokevirtual
    public void invoke4(){
        system.out.println( "he1lo");
        Thread t1 = null;
        t1.run();
    }
}

把当前的代码编译一下,看看具体的字节码是怎么描述当前方法的?
在这里插入图片描述

接下来我们通过示例代码拉体会下一个方法指令,看看会有什么不一样?

public class MethodInvokeReturnTest {
    
    //方法调用指令:invokeinterface
    public void invoke3(){
    
        Thread t1 = new Thread();
        ((Runnable)t1).run();
        
        Comparable<Integer> com = null;
        com.compareTo(123);
    }
}

把当前的代码编译一下,看看具体的字节码是怎么描述当前方法的?
在这里插入图片描述

那么针对于接口里的静态方法与非静态方法,调用之后又会是什么情况呢?

interface AA{
    
    public static void method1(){}
    
    public default void method2(){}
}
class BB implements AA{

}
public class InterfaceMethodTest{
    public static void main( string[] args){
        AA aa = new BB();
        aa.method2();
        AA.method1();
    }
}

把当前的代码编译一下,看看具体的字节码是怎么描述当前方法的?
在这里插入图片描述

三、通过示例代码来体会方法返回指令


方法调用结束前,需要进行返回。方法返回指令是根据返回值的类型区分的。

当我们返回值是boolean、byte、char、short和int类型采用ireturn表示

当我们返回值是float类型采用freturn表示

当我们返回值是double类型采用dreturn表示

当我们返回值是引用型采用areturn表示

还有一条return指令供声明为void的方法、实例初始化方法以及类和接口的类初始化方法使用。
在这里插入图片描述

示例指令讲解

通过ireturn指令,将当前函数操作数栈的顶层元素弹出,并将这个元素压入调用者函数的操作数栈中〈因为调用者非常关心函数的返回值),所有在当前函数操作数栈中的其他元素都会被丢弃。

如果当前返回的是synchronized方法,那么还会执行一个隐含的monitorexit指令,退出临界区

最后,会丢弃当前方法的整个帧,恢复调用者的帧,并将控制权转交给调用者。

接下来我们通过示例代码拉体会对应的方法指令,看看是怎么样的?

public class MethodInvokeReturnTest {
    
    //方法的返回指令
    public int returnInt(){
        int i = 50;
        return i;
    }
}

把当前的代码编译一下,看看具体的字节码是怎么描述当前方法的?
在这里插入图片描述

接下来我们通过示例代码拉体会其他方法返回指令,看看会有什么不一样?

public class MethodInvokeReturnTest {
    
    //方法的返回指令
    public double returnDouble(){
        return 0.0;
    }
    public string returnstring(){
        return "hello,wor1d" ;
    }
    public int[] returnArr(){
        return nu1l;
    }
    public float returnFloat(){
        int i = 10;
        return i;
    }
    public byte returnByte(){
        return 0;
    }
}

把当前的代码编译一下,看看具体的字节码是怎么描述当前方法的?
在这里插入图片描述

下面是本人的公众号:(有兴趣可以扫一下,文章会同步过去)
在这里插入图片描述

我是小白弟弟,一个在互联网行业的小白,立志成为一名架构师
https://blog.csdn.net/zhouhengzhe?t=1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhz小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值