JVM: 方法调用

文章目录

一、介绍

在JVM中,一共有五个字节码指令可以执行方法调用:

  • invokestatic: 调用静态方法。
  • invokespecial:调用对象的private方法、构造方法,以及使用super关键字调用父类实例的方法、构造方法、以及所实现接口的默认方法。
  • invokevirtual:调用对象的非private方法。
  • invokeinterface:调用接口对象的方法。
  • invokedynamic:用于调用动态方法,主要应用于lambda表达式中,机制极为复杂了解即可。

二、方法调用的原理

Invoke指令执行时,需要找到方法区中instanceKlass中保存的方法相关的字节码信息。但是方法区中有很多类,每一个类又包含很多个方法,怎么精确地确定到方法的位置呢?

1、静态绑定

  • 编译期间,invoke指令会携带一个参数符号引用,引用到常量池中的方法定义。方法定义中包含了类名+方法名+返回值+参数。
  • 在方法第一次调用时,这些符号引用就会被替换成内存地址的直接引用,这种方式称之为静态绑定。
  • 静态绑定适用于处理静态方法、私有方法、或者使用final修饰的方法,因为这些方法不能被继承之后重写。

2、动态绑定

(1)介绍

对于非static、非private、非final的方法,有可能存在子类重写方法,那么就需要通过动态绑定来完成方法地址绑定的工作。比如在下面这段代码中,调用的其实是Cat类对象的eat方法,但是编译完成之后虚拟机指令中调用的是Animal类的eat方法,这就需要在运行过程中通过动态绑定找到Cat类的eat方法,这样就实现了多态。

(2)原理

动态绑定是基于方法表来完成的,invokevirtual使用了虚方法表(vtable),invokeinterface使用了接口方法表(itable),整体思路类似。所以接下来使用invokevirtual和虚方法表来解释整个过程。

每个类中都有一个虚方法表,本质上它是一个数组,记录了方法的地址。子类方法表中包含父类方法表中的所有方法;子类如果重写了父类方法,则使用自己类中方法的地址进行替换。

产生invokevirtual调用时,先根据对象头中的类型指针找到方法区中InstanceClass对象,获得虚方法表。在根据方法表找到对应的对象,获得方法的地址,最后调用方法。

相关推荐
tongluowan00713 小时前
jvm垃圾回收器 - CMS-已弃用的垃圾回收器
jvm·cms·垃圾回收器
light blue bird21 小时前
主子表单控件图表带拖拽式控件工序管理组件
开发语言·jvm·信息可视化·桌面端winform
QWQ___qwq1 天前
Text2SQL 完整流程模拟详细笔记
jvm·笔记·oracle
light blue bird1 天前
可更新组装工序资源图表功能组件
开发语言·前端·jvm·.net·状态模式
light blue bird1 天前
组装工序资源功能工序路径菜单组件
jvm·数据库·winform·gdi+界面·多节点端
菜鸟是大神1 天前
JDK21-Windows安装
java·jvm·windows
Lei活在当下2 天前
先用起来,再理解,关于协程Coroutine应该知道的事
android·java·jvm
KobeSacre2 天前
JVM 总结
jvm
墨雪不会编程2 天前
C++ 进阶:虚函数与多态原理
java·jvm·c++
顺风尿一寸2 天前
从 FileOutputStream.write(byte) 到磁盘扇区:一次 Java 写入操作的完整内核穿越之旅
jvm