Java 方法调用的底层实现

本文深入探讨了Java中方法调用的底层实现,包括字节码指令的作用,如invokestatic、invokespecial、invokevirtual、invokeinterface和invokedynamic。解释了非虚方法与静态链接的关系,以及虚方法的动态链接和分派概念。文章还介绍了静态分派和动态分派的区别,以及Java中的单分派和多分派。最后,提到了Java 7引入的invokedynamic指令和方法句柄在实现动态类型语言和Lambda表达式中的应用。
摘要由CSDN通过智能技术生成

为什么要了解方法调用

我们写的代码,经过编译、经过类加载的各种阶段,进入了 JVM 的运行时数据区。

但作为程序员真正关心是代码的执行,代码的执行其实本质上是方法的执行,站在 JVM 的角度归根到底还是 字节码的执行 。

main 函数是 JVM 指令执行的起点,JVM 会创建 main 线程来执行 main 函数,以触发 JVM 一系列指令的执行,真正地把 JVM 跑起来。

接着,在我们的代码中,就是方法调用方法的过程,所以了解方法在 JVM 中的调用是非常必要的。

方法调用的字节码指令

一个方法的执行是通过调用字节码指令实现的,并且在Class常量池中有类的版本、字段、 方法 和接口等描述信息。即在Java类尚未加载的时候,方法以字节码的形式存在于Class常量池中。

附:Java字节码指令大全

这样说好像不能信服,我们随便写一个方法,通过 jclasslib (一个查看字节码的工具)来查看,如下:

我们知道了方法在哪里,但是怎么调用呢?关于方法调用,Java共提供了5个指令,来调用不同类型的方法:

  • invokestatic , 用来调用静态方法。
  • invokespecial ,用来调用私有实例方法、构造器、super关键字等。
  • invokevirtual , 用于调用非私有实例方法,比如 public 和 protected,大多数方法调用属于这一种。
  • invokeinterface ,和 invokevirtual 类似,但作用于接口类。
  • invokedynamic , 用于调用动态方法。

我们经常说的静态方法,实例方法等,实际上它们有一个比较官方的说法: 虚方法以及非虚方法。

非虚方法

什么叫非虚方法?

如果方法在编译期就确定了具体的调用版本,这个版本在 运行时是不可变的 ,这样的方法称为非虚方法。 一般来说包含以下五种:

  • 静态方法(static修饰)

  • 私有方法(private修饰)

  • 父类方法

  • 构造方法

  • final 修饰的方法(特例,因为被final修饰的方法就是不可变的方法,但实际还是使用 invokevirtual 指令),如下

    public final void invokeStatic() {
        System.out.println("invokestatic 调用静态方法");
    }
    复制代码

简单来说就是被 invokestatic 和 invokespecial 指令调用的方法,我们来验证一下。

invokestatic

调用静态方法:

public class InvokeStatic {
​
    public static void invokeStatic() {
        System.out.println("invokestatic 调用静态方法");
    }
​
    public static void main(String[] args) {
        //调用静态方法
        InvokeStatic.invokeStatic();
    }
}
复制代码

查看字节码:

我们可以看到被在main方法的字节码中有: invokestatic #5

invokestatic 我们知道,调用的是静态方法, #5 代表什么呢?我们通过 javap -v InvokeStatic.class 查看,发现 #5 后面有个注释,即 invokeStatic() 方法。

这个方法调用在编译期间就明确以常量池项的形式固化在字节码指令的参数之中了。

invokespecial

调用私有实例方法、构造器、super关键字等。

还是上面的代码,通过实例化:

public class InvokeStatic {
​
    public static void invokeStatic() {
        System.out.println("invokestatic 调用静态方法");
    }
​
    public static void main(String[] args) {
        //实例化
        Inv
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值