JAVA语言多态和动态语言实现原理
JAVA语言多态和动态语言实现原理
- 前言
- invoke指令
- invokestatic
- invokespecial
- invokevirtual
- invokeinteface
- invokedynamic
- Lambda
- 总结
前言
我们编码java文件,javac编译class文件,java运行class,JVM执行main方法,加载链接初始化对应类,确定类/对象调用函数,执行对应函数方法code字节码,执行引擎不断取指执行。本文主要介绍虚拟机加载链接初始化类后,在执行函数调用时虚拟机如何通过相关invoke指令,确定具体执行函数,并以此介绍JAVA语言中多态和动态语言实现原理。
invoke指令
虚拟机再实现函数调涉及invoke指令,分为如下5类:
| invoke指令 | 函数调用 |
|---|---|
| invokestatic | 执行类静态方法 |
| invokespecial | 执行对象构造器,私有方法,父类方法 |
| invokevirtual | 执行类对象的普通方法,(非静态,构造器,私有方法等), 虚拟机在运行期通过动态分派 |
| invokeinterface | 接口对象执行接口方法,虚拟机在运行期通过动态分派 |
| invokedynamic | 用户编码确定方法句柄 |
下面代码分别演示编译后函数调用使用invoke指令,使用jclasslib idea插件查看:
public class InvokeTestDemo extends AbsParent implements InterfaceParent {public static void main(String[] args) throws Throwable{InvokeTestDemo demo = new InvokeTestDemo();demo.test();}private void test() throws Throwable{// invokestatic 静态方法staticMethod();// invokespecial 构造方法new InvokeTestDemo();// invokespecial 私有方法privateMethod();// invokespecial 父类方法, 内部super.parentMethod();// invokevirtualfinalMethod();publicMethod();parentMethod();interfaceMethod();// invokeinterface 接口方法InterfaceParent iTest = this;iTest.interfaceMethod();// invokedynamicFunction<String, String> func = str -> "append " + str;func.apply("test");// MethodHandleAnimal animal = new Animal();say(animal);People people = new People();say(people);}public static void say(Object obj) throws Throwable {MethodHandles.Lookup lookup = MethodHandles.lookup();MethodType methodType = MethodType.methodType(void.class);MethodHandle methodHandle = lookup.findVirtual(obj.getClass(), "say", methodType);methodHandle.invoke(obj);}public static class Animal {public void say() {System.out.println("hello Animal");}}public static class People {public void say() {System.out.println("hello People");}}public static void staticMethod() {}private void privateMethod() {}public final void finalMethod() {}public void publicMethod() {}@Overridepublic void interfaceMethod() {}
}abstract class AbsParent {public void parentMethod() {}
}interface InterfaceParent {void interfaceMethod();
}
invokestatic
调用类静态方法,属于静态分派,编译期可确定调用方法,运行期不变。

invokespecial
调用对象构造器,私有方法,直接父类方法,属于静态分派,编译期可确定调用方法,运行期不变。

invokevirtual
调用对象普通方法(非对象构造器,私有方法,直接父类方法),运行期根据对象具体类型,再确定具体执行方法,这个便是语言多态特征。

在具体实现上,以HotSpot为例,HotSpot使用了与C++虚函数类似的机制,同时为了避免每个对象都维护一个虚函数表,设计了Oop-Klass模型,用Klass类保存类的元数据和虚函数表vtable (virtual method table)。
vtable生成:
1、递归生成父类vtable
2、覆盖重写方法
3、追加新定义方法
Class Animal {public void breathe() {}public void sound() {}}Class Cat extends Animal{@overridepublic void sound() {}public void run() {}
}
Animal vtable
| 方法 | 方法地址 |
|---|---|
| breathe | @Animal#breathe |
| sound | @Animal#sound |
Cat vtable
| 方法 | 方法地址 | 备注 |
|---|---|---|
| breathe | @Animal#breathe | 取自父类 |
| sound | @Cat#sound | 本类重写 |
| sound | @Cat#run | 本类追加 |
vtable是用空间换取时间,类对应klass维护相对应的vtable,发生函数调用时,操作步骤如下:
1、通过函数操作数栈,获取栈顶调用函数者。
2、函数调用者查找实际类型class,进而确定klass关联vtable。
3、通过函数编号,找到vtable函数编号的方法代码code。
4、读取code字节码指令,执行引擎执行指令。
invokeinteface
以接口调用接口类方法,运行期根据接口实现类型,再确定具体执行方法。

在具体实现上,以HotSpot为例,同vtable实现类似,接口是使用itable(inteface method table)实现方法动态分派。
itable存储格式如下:
itableOffsetEntry1
itableOffsetEntry2
……
itableOffsetEntryn
itableMethodEntry1
itableMethodEntry2
……
itableMethodEntryn
itable函数查找过程如下:
1、通过函数操作数栈,获取栈顶调用函数者。
2、函数调用者查找实际类型class,进而确定klass关联itable。
3、遍历itable查找接口entry对应itableOffsetEntry。
4、通过itableOffsetEntry
为什么需要itable,而不是用vtable去实现:
1、一个类继承是单继承,子类包含父类vtable,且和父类的函数编号是一致,可以直接使用父类的函数编号找到对应的子类实现函数。
2、一个类可以实现多个接口,而每个接口的函数编号是个接口相关,vtable无法解决多个对应接口的函数编号问题。
即:虚拟机规范规定,继承是单继承,实现是可实现多个接口。
invokedynamic
以上介绍invoke指令调用的函数流程实现是在虚拟机内部,编译器和虚拟机运行期完成调用方法查找并执行相应字节码,而invokedynamic指令则支持由用户编码确定方法句柄,具体查找过程如下:
1、JVM执行到invokedynamic指令时,它会首先查找与该指令关联的引导方法。
2、引导方法根据传入的参数动态生成和链接目标方法,并返回CallSite对象(封装了目标方法的所有信息,包括方法句柄、参数类型和返回类型)。
3、CallSite对象被创建并返回给invokedynamic指令,JVM就会将该指令与调用站点对象关联起来。
4、在后续的执行过程中,当再次遇到相同的invokedynamic指令时,JVM会直接通过调用站点对象调用目标方法,而无需再次执行引导方法。这种机制可以显著提高动态方法调用的性能。
某种意义上可以说invokedynamic指令与MethodHandle机制的作用是一样的。都是为了解决原有的4条”invoke”指令方法分派规则完全固化在虚拟机之中的问题。如何把查找目标方法的决定权从虚拟机转嫁到具体的用户代码中。
Lambda
lambda实现依赖invokedynamic执行,由编译器生成引导方法,生成调用点。
invokedynamic #13 <apply, BootstrapMethods #0>


过程如下:
1、Lambda 表达式解析常用引导方法,java.lang.invoke.LambdaMetafactory#metaFactory:
2、引导方法 metaMethod 根据这些参数生成 java.lang.invoke.CallSite 动态调用点
3、在引导方法中会动态生成一个模板匿名类
4、创建匿名类实例,执行方法调用。
总结
多态特性:虚拟机在运行时通过动态分派,查找确定要执行函数。
动态语言:虚拟机通过invokedynamic执行,由应用程序指定MethodHanle,确定函数调用者,方法,参数,调用方法等,实现动态语言。
参考: https://blog.csdn.net/weixin_47184173/article/details/109903542
相关文章:
JAVA语言多态和动态语言实现原理
JAVA语言多态和动态语言实现原理 前言invoke指令invokestaticinvokespecialinvokevirtualinvokeintefaceinvokedynamicLambda 总结 前言 我们编码java文件,javac编译class文件,java运行class,JVM执行main方法,加载链接初始化对应…...
阿里云-防火墙设置不当导致ssh无法连接
今天学网络编程的时候,看见有陌生ip连接,所以打开了防火墙禁止除本机之外的其他ip连接: 但是当我再次用ssh的时候,连不上了才发现大事不妙。 折腾了半天,发现阿里云上可以在线向服务器发送命令,所以赶紧把2…...
使用WebAssembly优化Web应用性能
💓 博客主页:瑕疵的CSDN主页 📝 Gitee主页:瑕疵的gitee主页 ⏩ 文章专栏:《热点资讯》 使用WebAssembly优化Web应用性能 引言 WebAssembly 简介 安装工具 创建 WebAssembly 项目 编写 WebAssembly 代码 编译 WebAssem…...
软件测试模型
软件测试模型是在软件开发过程中,用于指导软件测试活动的一系列方法和框架。这些模型帮助测试团队确定何时进行测试、测试什么以及如何测试,从而确保软件的质量和稳定性。 一 V模型 V模型是一种经典的软件测试模型,它由瀑布研发模型演变而来的测试模型…...
动态规划——两个数组的dp问题
目录 一、最长公共子序列 二、不同的子序列 三、通配符匹配 四、正则表达式匹配 五、两个字符串的最小ASCII删除和 六、最长重复子数组 七、交错字符串 一、最长公共子序列 最长公共子序列 第一步:确定状态表示 dp[i][j]:表示字符串 s1 的 [0&am…...
视频QoE测量学习笔记(二)
目录 自适应比特率(ABH或ABS) HAS:HTTP adaptive streaming 自适应本质: HAS正在解决传统流协议中主要关注的几个方面: DASH标准化原因 HAS发展 编码: 影响HAS系统的四个主要问题: 一个健全的HAS方…...
RSA算法详解:原理与应用
RSA算法详解:原理与应用 RSA算法是现代密码学的基石之一,广泛应用于安全通信、数据加密和身份验证等领域。本文将详细介绍RSA算法的原理、实现步骤以及实际应用。 一、RSA算法概述 RSA(Rivest-Shamir-Adleman)算法由Ron Rivest…...
YOLOv6-4.0部分代码阅读笔记-effidehead_fuseab.py
effidehead_fuseab.py yolov6\models\heads\effidehead_fuseab.py 目录 effidehead_fuseab.py 1.所需的库和模块 2.class Detect(nn.Module): 3.def build_effidehead_layer(channels_list, num_anchors, num_classes, reg_max16, num_layers3): 1.所需的库和模块 impo…...
特朗普概念股DJT股票分析:为美国大选“黑天鹅事件”做好准备
猛兽财经核心观点: (1)特朗普媒体科技集团的股价近期已经从年初至今的高点下跌了35%以上。 (2)该公司将面临一个重大的黑天鹅事件。 (3)这一结果将对特朗普媒体科技集团产生重大影响。 随着投资…...
【MySQL】 运维篇—故障排除与性能调优:常见故障的排查与解决
数据库系统在运行过程中可能会遇到各种故障,如性能下降、连接失败、数据损坏等。及时有效地排查和解决这些故障,对于保证系统的稳定性和数据的完整性至关重要。 常见故障及排查方法 1. 数据库连接失败 故障描述:应用程序无法连接到数据库&…...
Android R S T U版本如何在下拉栏菜单增加基本截图功能
本文主要是MTK增加下拉栏开关菜单,功能实现为基本的截图功能,metrics_constants.proto修改 QuickSetting 新增快捷设置图标,以便对应getMetricsCategory获取;一个布局文件,一个配置加载合入实现,一个新增想要实现截图的类。 /frameworks/base/proto/src/metrics_constan…...
C#二叉树原理及二叉搜索树代码实现
一、概念 二叉树(Binary Tree)是一种树形数据结构,其中每个节点最多有两个子节点,分别称为左子节点和右子节点。二叉树的每个节点包含三个部分:一个值、一个指向左子节点的引用和一个指向右子节点的引用。 二、二叉树…...
.eslintrc.js 的解释
如果您的项目中没有 .eslintrc.js 文件,您可以按以下步骤创建并配置 ESLint: 1. 创建 ESLint 配置文件 在您的项目根目录下创建一个新的文件,命名为 .eslintrc.js。 2. 配置 ESLint 规则 在 .eslintrc.js 文件中添加以下内容,…...
确保企业架构与业务的一致性与合规性:数字化转型中的关键要素与战略实施
在现代企业的数字化转型过程中,确保企业架构(Enterprise Architecture, EA)与企业业务的紧密一致性与合规性至关重要。无论是在战略层面还是运营层面,EA都为企业的未来发展提供了清晰的蓝图,确保企业在应对复杂的业务环…...
goframe开发一个企业网站 前端界面 拆分界面7
将页面拆出几个公用部分 在resource/template/front创建meta.html header.html footer.html meta.html <head><meta charset"utf-8"><meta content"widthdevice-width, initial-scale1.0" name"viewport"><title>{{.…...
Postman断言与依赖接口测试详解!
在接口测试中,断言是不可或缺的一环。它不仅能够自动判断业务逻辑的正确性,还能确保接口的实际功能实现符合预期。Postman作为一款强大的接口测试工具,不仅支持发送HTTP请求和接收响应,还提供了丰富的断言功能,帮助测试…...
github打不开网络问题
当打开github出现超时或者网络不能访问的情况时,我们进行如下方法解决: 1,ping gitbub.com查看域名分析的DNS IP C:\Users\86156>ping github.com 正在 Ping github.com [20.205.243.166] 具有 32 字节的数据: 来自 20.205.243.166 的回复…...
智能教育工具:基于SpringBoot的在线试题库
1 绪论 1.1 研究背景 现在大家正处于互联网加的时代,这个时代它就是一个信息内容无比丰富,信息处理与管理变得越加高效的网络化的时代,这个时代让大家的生活不仅变得更加地便利化,也让时间变得更加地宝贵化,因为每天的…...
typescript 如何跳过ts类型检查?
文章目录 前言any类型条件判断进行使用断言加注释跳过ts检查 前言 typescript 的使用,虽然让代码更加规范,利于维护,但也给开发带来很多麻烦。为了跳过很多ts的类型检查,大家也是费尽心思,下面就介绍一些常用的方式&a…...
详解ReentrantLock--三种加锁方式
目录 介绍AQS: 直观方式解释加锁的流程: Node是什么:它里面有什么属性呢 图解队列的排队过程: 源码分析三种加锁流程: 我们先讲解一下非公平锁的加锁流程: Lock()方式加锁: 在源码里对于Lock()的解…...
别再瞎调优先级了!STM32CubeMX配置FreeRTOS任务调度器的5个实战避坑点
别再瞎调优先级了!STM32CubeMX配置FreeRTOS任务调度器的5个实战避坑点 刚接触FreeRTOS的嵌入式开发者,往往会在STM32CubeMX的图形化配置界面里迷失方向。那些看似简单的下拉菜单和复选框,背后却藏着让系统崩溃的陷阱。我曾见过一个工程师将任…...
高效数据采集解决方案:快手内容获取工具的技术实现与应用指南
高效数据采集解决方案:快手内容获取工具的技术实现与应用指南 【免费下载链接】kuaishou-crawler As you can see, a kuaishou crawler 项目地址: https://gitcode.com/gh_mirrors/ku/kuaishou-crawler 在信息爆炸的时代,如何高效、合规地获取网络…...
ViT图像分类-中文-日常物品完整指南:4090D单卡环境配置与中文类别映射说明
ViT图像分类-中文-日常物品完整指南:4090D单卡环境配置与中文类别映射说明 想试试用AI模型来识别你手机里的照片吗?比如,拍一张桌上的水杯、键盘或者零食,让模型告诉你它是什么。今天要介绍的这个工具,就能帮你轻松实…...
从黑客攻防角度看网络命令:如何用ping/tracert/nslookup发现网络安全隐患
网络命令的攻防实战:用基础工具发现隐藏的安全威胁 当大多数人还在把ping、tracert这些基础网络命令当作简单的连通性测试工具时,安全工程师已经将它们变成了发现网络威胁的"显微镜"。这些看似简单的命令行工具,在专业的安全分析场…...
GLM-4-9B-Chat-1M惊艳效果:碳中和白皮书(120页)中的技术路径拆解、时间节点校验与政策匹配度评分
GLM-4-9B-Chat-1M惊艳效果:碳中和白皮书(120页)中的技术路径拆解、时间节点校验与政策匹配度评分 1. 项目背景与核心能力 今天要给大家展示一个让人眼前一亮的技术应用场景——用GLM-4-9B-Chat-1M这个本地部署的大模型,来深度分…...
Discord社群运营神器:用AI自动回复提升活跃度的完整指南
Discord社群运营神器:用AI自动回复提升活跃度的完整指南 在数字社交时代,Discord已经从一个游戏语音工具成长为全球最受欢迎的社群平台之一。无论是Web3项目、开源社区还是兴趣小组,Discord都成为了连接成员的核心枢纽。但作为社群运营者&…...
手把手教你用Cline插件5分钟搞定DeepSeek-R1模型接入(附硅基流动平台2000万Token福利)
5分钟极速上手:用Cline插件无缝对接DeepSeek-R1大模型实战指南 当你第一次听说只需要5分钟就能让一个强大的AI模型为你工作时,可能会觉得这像是某种夸张的营销话术。但作为一个曾经花了整整三天时间才搞定第一个模型接入的开发者,我可以负责任…...
Mac用户的移动Win10工坊:从WTG配置到驱动、激活、文件共享的完整避坑指南
Mac用户的移动Win10工坊:从WTG配置到驱动、激活、文件共享的完整避坑指南 当Mac用户需要运行Windows应用时,双系统方案往往是最佳选择。而通过Windows To Go(WTG)技术将Win10安装在移动硬盘上,不仅保留了Mac原生系统的…...
护士执业资格考试历年真题及答案解析电子版PDF(2011-2025年)
2026年护士执业资格考试时间为2026年4月11-12日。为助力广大考生高效备考,小编精心整理了涵盖2011年至2025年的护士执业资格考试真题试卷及详细答案解析,包含《专业实务》和《实践能力》,高清PDF电子版,可打印,方便…...
RePKG终极指南:Wallpaper Engine资源提取与转换的完整解决方案
RePKG终极指南:Wallpaper Engine资源提取与转换的完整解决方案 【免费下载链接】repkg Wallpaper engine PKG extractor/TEX to image converter 项目地址: https://gitcode.com/gh_mirrors/re/repkg 你是否曾经遇到过这样的问题?在Wallpaper Eng…...
