Java | JVM虚方法调用那些事

微信公众号:吉姆餐厅ak
学习更多源码知识,欢迎关注。
在这里插入图片描述


概述

在以前面试过程中,会遇到一些这样的面试题:说一下java语言 静态绑定 和 动态绑定的本质区别?
这道题听起来好像没怎么接触过,换个问法可能就很清晰了:重载和重写的实现原理和区别。

具体来分析以下这两点:

方法调用
方法表

方法调用

java是一种半编译半解释型语言,也就是class文件会被解释成机器码,而方法调用也会被解释成具体的方法调用指令,大致可以分为以下五类指令:

  • invokestatic:调用静态方法;
  • invokespecial:调用实例构造方法,私有方法和父类方法;
  • invokevirtual:调用虚方法;
  • invokeinterface:调用接口方法,在运行时再确定一个实现此接口的对象;
  • invokedynamic:在运行时动态解析出调用点限定符所引用的方法之后,调用该方法;

注意:invokedynamic 指令是jdk1.7才加入的,但是在jdk1.7中并没有开始使用。在jdk1.8中才开始大量使用,主要就是我们大量用的 lambda 表达式。

如果在编译时期解析,那么指令指向的方法就是静态绑定,也就是private,final,static和构造方法,也就是上面的invokestaticinvokespecial指令,这些在编译器已经确定具体指向的方法。而接口和虚方法调用无法找到真正需要调用的方法,因为它可能是定义在子类中的方法,所以这种在运行时期才能明确类型的方法我们成为动态绑定。

具体来看一下:

public class StaticBind {
    public static void main(String[] args) {
        Father son = new Son1();
        son.run();
    }
}
class Father{
    public void run(){
        System.out.println("father");
    }
}
class Son1 extends  Father{
    @Override
    public void run(){
        System.out.println("son1");
    }
}

通过javap -c看一下编译后的机器码指令,如下:
这里写图片描述
可以看到第4行是invokespecial指令,构造方法 init 指令。第9行是invokevirtual指令,Method com/iyb/ak/study/Father.run:()该指令表明是父类的方法,但这只是在编译时确定的,在执行时却会从方法表中找到真正重写的方法。

在来看一下重载时的一种虚引用的一种场景:

/**
 * Created by zhangshukang on 2018/8/2.
 */
public class StaticBind {

    public void run(Father father){
        System.out.println("father");

    }
    public void run(Son1 son1){
        System.out.println("son1");

    }
    public void run(Son2 son2){
        System.out.println("son2");

    }
    public static void main(String[] args) {
        Son1 son1 = new Son1();
        Son2 son2 = new Son2();
        StaticBind staticBind = new StaticBind();
        staticBind.run(son1);
        staticBind.run(son2);

    }
}
class Father{}

class Son1{}

class Son2{}

javap -c看一下编译后的机器码指令:
这里写图片描述
上述代码中,在编译阶段,Java编译器会根据参数的静态类型决定调用哪个重载版本,但在有些情况下,重载的版本不是唯一的,这样只能选择一个“更加合适的版本”进行调用,所以不建议在实际项目中使用这种模糊的方法重载。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值