当前位置: 首页 > news >正文

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>

lambda引导方法
引导方法

过程如下:
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文件&#xff0c;javac编译class文件&#xff0c;java运行class&#xff0c;JVM执行main方法&#xff0c;加载链接初始化对应…...

阿里云-防火墙设置不当导致ssh无法连接

今天学网络编程的时候&#xff0c;看见有陌生ip连接&#xff0c;所以打开了防火墙禁止除本机之外的其他ip连接&#xff1a; 但是当我再次用ssh的时候&#xff0c;连不上了才发现大事不妙。 折腾了半天&#xff0c;发现阿里云上可以在线向服务器发送命令&#xff0c;所以赶紧把2…...

使用WebAssembly优化Web应用性能

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 使用WebAssembly优化Web应用性能 引言 WebAssembly 简介 安装工具 创建 WebAssembly 项目 编写 WebAssembly 代码 编译 WebAssem…...

软件测试模型

软件测试模型是在软件开发过程中&#xff0c;用于指导软件测试活动的一系列方法和框架。这些模型帮助测试团队确定何时进行测试、测试什么以及如何测试&#xff0c;从而确保软件的质量和稳定性。 一 V模型 V模型是一种经典的软件测试模型,它由瀑布研发模型演变而来的测试模型…...

动态规划——两个数组的dp问题

目录 一、最长公共子序列 二、不同的子序列 三、通配符匹配 四、正则表达式匹配 五、两个字符串的最小ASCII删除和 六、最长重复子数组 七、交错字符串 一、最长公共子序列 最长公共子序列 第一步&#xff1a;确定状态表示 dp[i][j]&#xff1a;表示字符串 s1 的 [0&am…...

视频QoE测量学习笔记(二)

目录 自适应比特率&#xff08;ABH或ABS&#xff09; HAS:HTTP adaptive streaming 自适应本质&#xff1a; HAS正在解决传统流协议中主要关注的几个方面&#xff1a; DASH标准化原因 HAS发展 编码&#xff1a; 影响HAS系统的四个主要问题&#xff1a; 一个健全的HAS方…...

RSA算法详解:原理与应用

RSA算法详解&#xff1a;原理与应用 RSA算法是现代密码学的基石之一&#xff0c;广泛应用于安全通信、数据加密和身份验证等领域。本文将详细介绍RSA算法的原理、实现步骤以及实际应用。 一、RSA算法概述 RSA&#xff08;Rivest-Shamir-Adleman&#xff09;算法由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股票分析:为美国大选“黑天鹅事件”做好准备

猛兽财经核心观点&#xff1a; &#xff08;1&#xff09;特朗普媒体科技集团的股价近期已经从年初至今的高点下跌了35%以上。 &#xff08;2&#xff09;该公司将面临一个重大的黑天鹅事件。 &#xff08;3&#xff09;这一结果将对特朗普媒体科技集团产生重大影响。 随着投资…...

【MySQL】 运维篇—故障排除与性能调优:常见故障的排查与解决

数据库系统在运行过程中可能会遇到各种故障&#xff0c;如性能下降、连接失败、数据损坏等。及时有效地排查和解决这些故障&#xff0c;对于保证系统的稳定性和数据的完整性至关重要。 常见故障及排查方法 1. 数据库连接失败 故障描述&#xff1a;应用程序无法连接到数据库&…...

Android R S T U版本如何在下拉栏菜单增加基本截图功能

本文主要是MTK增加下拉栏开关菜单,功能实现为基本的截图功能,metrics_constants.proto修改 QuickSetting 新增快捷设置图标,以便对应getMetricsCategory获取;一个布局文件,一个配置加载合入实现,一个新增想要实现截图的类。 /frameworks/base/proto/src/metrics_constan…...

C#二叉树原理及二叉搜索树代码实现

一、概念 二叉树&#xff08;Binary Tree&#xff09;是一种树形数据结构&#xff0c;其中每个节点最多有两个子节点&#xff0c;分别称为左子节点和右子节点。二叉树的每个节点包含三个部分&#xff1a;一个值、一个指向左子节点的引用和一个指向右子节点的引用。 二、二叉树…...

.eslintrc.js 的解释

如果您的项目中没有 .eslintrc.js 文件&#xff0c;您可以按以下步骤创建并配置 ESLint&#xff1a; 1. 创建 ESLint 配置文件 在您的项目根目录下创建一个新的文件&#xff0c;命名为 .eslintrc.js。 2. 配置 ESLint 规则 在 .eslintrc.js 文件中添加以下内容&#xff0c;…...

确保企业架构与业务的一致性与合规性:数字化转型中的关键要素与战略实施

在现代企业的数字化转型过程中&#xff0c;确保企业架构&#xff08;Enterprise Architecture, EA&#xff09;与企业业务的紧密一致性与合规性至关重要。无论是在战略层面还是运营层面&#xff0c;EA都为企业的未来发展提供了清晰的蓝图&#xff0c;确保企业在应对复杂的业务环…...

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断言与依赖接口测试详解!

在接口测试中&#xff0c;断言是不可或缺的一环。它不仅能够自动判断业务逻辑的正确性&#xff0c;还能确保接口的实际功能实现符合预期。Postman作为一款强大的接口测试工具&#xff0c;不仅支持发送HTTP请求和接收响应&#xff0c;还提供了丰富的断言功能&#xff0c;帮助测试…...

github打不开网络问题

当打开github出现超时或者网络不能访问的情况时&#xff0c;我们进行如下方法解决&#xff1a; 1&#xff0c;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 研究背景 现在大家正处于互联网加的时代&#xff0c;这个时代它就是一个信息内容无比丰富&#xff0c;信息处理与管理变得越加高效的网络化的时代&#xff0c;这个时代让大家的生活不仅变得更加地便利化&#xff0c;也让时间变得更加地宝贵化&#xff0c;因为每天的…...

typescript 如何跳过ts类型检查?

文章目录 前言any类型条件判断进行使用断言加注释跳过ts检查 前言 typescript 的使用&#xff0c;虽然让代码更加规范&#xff0c;利于维护&#xff0c;但也给开发带来很多麻烦。为了跳过很多ts的类型检查&#xff0c;大家也是费尽心思&#xff0c;下面就介绍一些常用的方式&a…...

详解ReentrantLock--三种加锁方式

目录 介绍AQS: 直观方式解释加锁的流程&#xff1a; Node是什么&#xff1a;它里面有什么属性呢 图解队列的排队过程&#xff1a; 源码分析三种加锁流程&#xff1a; 我们先讲解一下非公平锁的加锁流程&#xff1a; Lock()方式加锁&#xff1a; 在源码里对于Lock()的解…...

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

可靠性+灵活性:电力载波技术在楼宇自控中的核心价值

可靠性灵活性&#xff1a;电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中&#xff0c;电力载波技术&#xff08;PLC&#xff09;凭借其独特的优势&#xff0c;正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据&#xff0c;无需额外布…...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

大语言模型如何处理长文本?常用文本分割技术详解

为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

基于matlab策略迭代和值迭代法的动态规划

经典的基于策略迭代和值迭代法的动态规划matlab代码&#xff0c;实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...