【04】JVM是如何执行方法调用的

一、重载与重写

1.重载

Java编译器会根据所传入参数的生命类型选取重载方法,选取的过程分为三个阶段
Created with Raphaël 2.3.0 开始 不考虑基本类型自动装拆箱以及可变长参数的情况下选取重载方法 Y or N 结束 允许基本类型自动装拆箱以及不允许可变长参数的情况下选取重载方法 Y or N 结束 允许基本类型自动装拆箱以及允许可变长参数的情况下选取重载方法 结束 yes no yes no

若Java编译器在同一个阶段找到多个适配的方法,则会其中选择一个最为贴切的,决定贴切程度的关键就是形式参数类型的继承关系。编译器会认为子类更为贴切。

举个例子说明下上面这句话

java 复制代码
void invoke(Object obj, Object... args) { ... }
void invoke(String s, Object obj, Object... args) { ... }

invoke(null, 1);    // 调用第二个 invoke 方法,因为String是Object的子类
invoke(null, 1, 2); // 调用第二个 invoke 方法,因为String是Object的子类
invoke(null, new Object[]{1}); // 只有手动绕开可变长参数的语法糖,
                               // 才能调用第一个 invoke 方法

2.重写

如果子类定义了与父类中非私有方法同名的方法,且这两个方法的参数类型相同就是重写

二、JVM的静态绑定和动态绑定

Java虚拟机中的静态绑定指的是在解析时能够直接识别目标方法的情况,动态绑定指的是在运行过程中根据调用者的动态类型来识别目标方法的情况

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

1.invokestatic:用于调用静态方法

2.invokespecial:用于调用私有实例方法、构造器以及使用super关键字调用父类的实例方法或构造器,和所实现接口的默认方法

3.invokevirtual:用于调用非私有实例方法

4.invokeinterface:用于调用接口方法

5.invokedynamic:用于调用动态方法

Java虚拟机中采取了用空间换取时间的策略来实现动态绑定,为每个类生成一张方法表,用以快速定位目标方法。

1.方法表

方法表本质上是一个数组,每个数组元素指向一个当前类及其祖先类中的非私有的实例方法。方法表中有两个特点:1.子类方法表中包含父类方法表中的所有方法 2.子类方法在方法表中的索引值,与它所重写的父类方法的索引值相同

方法调用指令中的符号引用会在执行之前解析成实际引用。对于静态绑定的方法调用而言,实际引用指向具体的目标方法;对于动态绑定的方法调用而言,实际引用是方法表的索引值。

2.内联缓存

虚函数是有一定性能消耗的,有多种手段用来优化虚函数,比如即时编译的两种优化手段:1.内联缓存 2.方法内联

内联缓存,缓存虚方法调用中调用者的动态类型,以及该类型所对应的目标方法。在之后的执行过程中,若碰到已缓存的类型,会直接调用该类型对应的目标方法;没有碰到已缓存的类型,则会退化至使用基于方法表的动态绑定。

相关推荐
重生之我在20年代敲代码25 分钟前
strncpy函数的使用和模拟实现
c语言·开发语言·c++·经验分享·笔记
爱上语文27 分钟前
Springboot的三层架构
java·开发语言·spring boot·后端·spring
longlongqin32 分钟前
JVM 内存结构?
jvm
编程零零七3 小时前
Python数据分析工具(三):pymssql的用法
开发语言·前端·数据库·python·oracle·数据分析·pymssql
2401_858286114 小时前
52.【C语言】 字符函数和字符串函数(strcat函数)
c语言·开发语言
铁松溜达py4 小时前
编译器/工具链环境:GCC vs LLVM/Clang,MSVCRT vs UCRT
开发语言·网络
everyStudy4 小时前
JavaScript如何判断输入的是空格
开发语言·javascript·ecmascript
C-SDN花园GGbond5 小时前
【探索数据结构与算法】插入排序:原理、实现与分析(图文详解)
c语言·开发语言·数据结构·排序算法
迷迭所归处6 小时前
C++ —— 关于vector
开发语言·c++·算法
架构文摘JGWZ6 小时前
Java 23 的12 个新特性!!
java·开发语言·学习