【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.方法内联

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

相关推荐
来恩100335 分钟前
C# 类与对象详解
开发语言·c#
komo莫莫da1 小时前
寒假刷题Day19
java·开发语言
ElseWhereR1 小时前
C++ 写一个简单的加减法计算器
开发语言·c++·算法
※DX3906※2 小时前
cpp实战项目—string类的模拟实现
开发语言·c++
wjs20242 小时前
Nginx 安装配置指南
开发语言
美味小鱼3 小时前
实践Rust:编写一个猜数字游戏
开发语言·游戏·rust
Dr.勿忘3 小时前
C#面试常考随笔8:using关键字有哪些用法?
开发语言·unity·面试·c#·游戏引擎
dal118网工任子仪3 小时前
92,[8] 攻防世界 web Web_php_wrong_nginx_config
开发语言·php
wjs20243 小时前
SQLite Update 语句详解
开发语言
加油,旭杏4 小时前
【go语言】接口
开发语言·后端·golang