JVM解释方法的执行

前言

class文件被加载到内存中,JVM如何执行类方法?下面我们来看一下方法的人生。

重写与重载

重写与重载对与我们并不陌生,java作为面向对象的语言,有封装、继承、多态三大特性,而重写是多态的一个体现,而重载是参数不同的同名方法。

重载
但是对于JVM并没有重载这个概念,在源代码编译时就已经指定了实际的方法,那么指定的具体过程是怎么样的呢?编译器根据传入参数的声明类型(注意与实际类型区分)来选择重载,选取分为三个阶段:

  1. 不考虑自动拆装箱以及可变长参数的情况下选取方法
  2. 允许自动拆装箱,但是不允许可变长参数
  3. 允许自动拆装箱和可变长参数

重写

而重写会根据调用者的动态类型选取实际的目标方法。JVM识别方法主要通过类名、方法名、以及方法描述符(方法描述符由方法的参数类型以及返回类型构成)。JVM对于方法重写的判定也基于方法描述符,子类定义了与父类非私有、非静态的方法、当方法描述符相同时判定为重写。

方法的调用

字节码中与调用相关的指令有五种:

  • invokestatic:调用静态方法,

  • invokespecial:调用私有实例方法,构造器,以及supper调用父类的实例方法或构造器和所以实现接口的默认方法

  • invokevirtual:调用非私有实例方法

  • invokeinterfance:调用接口方法

  • invokedynamic:调用动态方法

编译过程中,不知道目标方法的内存地址,用符号引用来表示,符号引用包括目标方法的类或接口名字,以及目标方法的方法名和方法描述符,符号引用存入class文件的常量池中,根据目标方法分为接口引用和非接口引用,在执行解析时会将符号引用替换为实际引用。

非接口引用,假如符号引用指向类C:

  • 在C中查找符号名字及描述符的方法
  • 如果没有找到,C的父类中搜索,一直到Object
  • 如果没有找到,C的直接实现或间接实现的接口搜索,这一步得到的目标方法是非私有非静态,如果目标方法在间接实现的接口中,则需满足C与该接口之间没有其他符合条件的目标方法,如果多个符符合,任意返回

接口引用,假设执行接口I:

  • I中查找符合名字和描述符的方法
  • 在Object的公有实例中搜索
  • 在I的超接口中搜索,要求与非接口的引用一致

经过对符号引用的的解析,符号引用解析成了实际引用,可以静态绑定的方法,实际引用是指向方法的指针。需要动态绑定的方法调用,实际引用是一个方法表的索引。

方法表

在写类加载机制的那篇博客中曾经说过,在类加载的准备阶段有的虚拟机会生成一个类的方法表,这个方法表就是用来动态确定方法调用的。

方法表其实就是一个数组,每个元素都指向当前类或者祖先类中非私有的实例方法,但是方法表还需要满足两个条件:子类包含父类的所有方法,并且子类重写的方法与父类的方法索引要相同。在实际的调用过程中,JVM根据调用者的实际类型在方法表中获取目标方法

当然方法表作为定位目标方法的一种手段仅存在解析执行中,在即时编译下还有更好的方法比如:内联缓存、方法内联

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值