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

【07】JVM是怎么实现invokedynamic的

在Java中,方法调用会被编译为invokeStaticinvokeSpecialinvokVirtual以及invokeInterface四种指令。这些指令与包含目标方法类名、方法名以及方法描述符的符号引用捆绑,在实际运行之前,JVM根据这个符号引用链接到具体目标方法。

JDK7 引入新的指令invodeDynamic该指令的调用机制抽象出调用点这一个概念,并允许应用程序将调用点链接至任意符合条件的方法上。同时JDK7 还配套引入了更加低层、更加抽象的方法抽象:方法句柄(invokedynamic 底层机制的基石:方法句柄。)。

一、方法句柄

1.方法句柄概念

强类型,能够被直接执行的引用。
方法句柄的类型是由所指向方法的参数以及返回类型组成的。它是用来确认方法句柄是否适配的唯一关键。

  • 方法句柄的获取
class Foo {private static void bar(Object o) {..}public static Lookup lookup() {return MethodHandles.lookup();}
}// 获取方法句柄的不同方式
MethodHandles.Lookup l = Foo.lookup(); // 具备 Foo 类的访问权限
Method m = Foo.class.getDeclaredMethod("bar", Object.class);
MethodHandle mh0 = l.unreflect(m);MethodType t = MethodType.methodType(void.class, Object.class);
MethodHandle mh1 = l.findStatic(Foo.class, "bar", t);
  • 方法句柄的权限
    与反射 API 不同,其权限检查是在句柄的创建阶段完成的。在实际调用过程中,JVM不会检查方法句柄的权限。

方法句柄的访问权限不取决于方法句柄的创建位置,而是取决于 Lookup对象的创建位置

举个例子,对于一个私有字段,如果 Lookup 对象是在私有字段所在类中获取的,则这个Lookup对象便拥有对该私有字段的访问权限,
即使是在所在类的外边,也能够通过该 Lookup 对象创建该私有字段的getter 或 setter

2.方法句柄的操作

  1. 方法句柄的调用有两种模式:
  • invokeExact(需要严苛匹配参数类型)
    一个方法句柄将接收一个 Object 类型的参数,如果你直接传入String作为实际参数,则方法句柄的调用会在运行时抛出方法类型不匹配的异常
  • invoke(自动适配参数类型)
    invoke 会调用 MethodHandle.asType方法,生成一个适配器方法句柄,对传入的参数进行适配,再调用原方法句柄;调用原方法句柄的返回值同样会先进行适配,然后再返回给调用者。
  1. 方法句柄支持增删改参数的操作
  • 改操作:MethodHandle.asType 方法
  • 删操作:将传入的部分参数就地抛弃,再调用另一个方法句柄。它对应的API 是 MethodHandles.dropArguments方法
  • 增操作:它会往传入的参数中插入额外的参数,再调用另一个方法句柄,它对应的 API 是 MethodHandle.bindTo 方法;Java 8 中捕获类型的 Lambda 表达式便是用这种操作来实现的
增操作还可以用来实现方法的柯里化。举个例子,有一个指向 f(x, y) 的方法句柄,我们可以通过将 x 绑定为 4,生成另一个方法句柄 g(y) = f(4, y)。
在执行过程中,每当调用 g(y) 的方法句柄,它会在参数列表最前面插入一个 4,再调用指向 f(x, y) 的方法句柄。

柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术

3.方法句柄的实现

方法句柄的调用和反射调用一样,都是间接调用。因此,它也会面临无法内联的问题。不过,与反射调用不同的是,方法句柄的内联瓶颈在于即时编译器能否将该方法句柄识别为常量。

二、invokeDynamic指令

1.调用点介绍

invokedynamic 是 Java 7 引入的一条新指令,用以支持动态语言的方法调用。具体来说,它将调用点(CallSite)抽象成一个 Java 类,并且将原本由 Java 虚拟机控制的方法调用以及方法链接暴露给了应用程序。在运行过程中,每一条 invokedynamic 指令将捆绑一个调用点,并且会调用该调用点所链接的方法句柄。
在第一次执行 invokedynamic 指令时,Java 虚拟机会调用该指令所对应的启动方法(BootStrap Method),来生成前面提到的调用点,并且将之绑定至该 invokedynamic 指令中。在之后的运行过程中,Java 虚拟机则会直接调用绑定的调用点所链接的方法句柄。

invokedynamic 的目的,就是将调用点与目标方法的链接交由应用程序来做,并且依赖于应用程序对目标方法进行验证。所以,如果应用程序将赛跑方法链接至兔子的睡觉方法,那也只能怪应用程序自己了。

2.Java8 中lambda表达式

Java8中的lambda是借助于invokeDynamic来实现的。

具体来说,Java 编译器利用 invokedynamic 指令来生成实现了函数式接口的适配器。

函数式接口指的是仅包括一个非 default 接口方法的接口,一般通过 @FunctionalInterface 注解,不过就算是没有使用该注解,Java 编译器也会将符合条件的接口辨认为函数式接口

int x = ..
IntStream.of(1, 2, 3).map(i -> i * 2).map(i -> i * x);上面这段代码会对 IntStream 中的元素进行两次映射。映射方法 map 所接收的参数是 IntUnaryOperator(这是一个函数式接口)。
也就是说,在运行过程中我们需要将 i->i*2 和 i -> i*x 这两个lambda表达式转化成IntUnaryOperator实例,
这个转换过程就是通过invokeDynamic实现的;在编译过程中,Java 编译器会对 Lambda 表达式进行解语法糖(desugar),
生成一个方法来保存 Lambda 表达式的内容。该方法的参数列表不仅包含原本 Lambda 表达式的参数,还包含它所捕获的变量。
(注:方法引用,如 Horse::race,则不会生成生成额外的方法。)在上面那个例子中,第一个 Lambda 表达式没有捕获其他变量,而第二个 Lambda 表达式(也就是 i->i*x)则会捕获局部变量 x。
这两个 Lambda 表达式对应的方法如下所示。可以看到,所捕获的变量同样也会作为参数传入生成的方法之中。

相关文章:

【07】JVM是怎么实现invokedynamic的

在Java中,方法调用会被编译为invokeStatic,invokeSpecial,invokVirtual以及invokeInterface四种指令。这些指令与包含目标方法类名、方法名以及方法描述符的符号引用捆绑,在实际运行之前,JVM根据这个符号引用链接到具体…...

使用API有效率地管理Dynadot域名,查看参与的拍卖列表

前言 Dynadot是通过ICANN认证的域名注册商,自2002年成立以来,服务于全球108个国家和地区的客户,为数以万计的客户提供简洁,优惠,安全的域名注册以及管理服务。 Dynadot平台操作教程索引(包括域名邮箱&…...

Linux 基本指令讲解

linux 基本指令 clear 清屏 Alt Enter 全屏/退出全屏 pwd 显示当前用户所处路径 cd 改变目录 cd /root/mikecd … 返回上级目录cd - 返回最近所处的路径cd ~ 直接返回当前用户自己的家目 roor 中:/root普通用户中:/home/mike mkdir 创建一个文件夹(d) …...

PRE_EMPHASIS

PRE_EMPASIS属性用于提高高频信号的信号完整性 其通过传输线遭受高频损耗。发射机 预加重(pre_EMPASIS)功能允许对某些信号驱动器进行预加重 I/O标准。 提示:发射机的预加重可以与接收机的均衡相结合,以提高 整体信号完整性。 理想…...

【QT常用技术讲解】多线程处理+全局变量处理异步事件并获取多个线程返回的结果

前言 QTableView加入勾选项后(参考【QT常用技术讲解】QTableView添加QCheckBox、QPushButton),如果支持右键菜单功能,此时就有统一执行多个异步事件,并且统一输出到界面的需求了,本篇结合多线程共享全局变量…...

数组列表中的最大距离

给定 m 个数组,每个数组都已经按照升序排好序了。现在你需要从两个不同的数组中选择两个整数(每个数组选一个)并且计算它们的距离。两个整数 a 和 b 之间的距离定义为它们差的绝对值 |a-b| 。你的任务就是去找到最大距离 示例 1:…...

C语言新手小白详细教程(7)指针和指针变量

希望文章能够给到初学的你一些启发~ 如果觉得文章对你有帮助的话,点赞 关注 收藏支持一下笔者吧~ 阅读指南: 开篇说明1、指针的定义接下来我们用图示的形式来解释一下 指针:2、申明指针变量3、取地址符 &4、为指针…...

Kafka保证消息不丢失

Kafka保证消息不丢失 生产者发送消息到Broker丢失 设置异步发送 回调方法中的参数Exception e如果为空 代表发送成功,如果不为空代表发送失败出现异常 消息在Broker中丢失 kafka集群中存在分区机制 分区中分为leader和follower副本 leader负责读写,而follower只负责数据…...

数据结构+基数排序算法

一、问题描述 实现英文单词按字典序排列的基数排序算法 编写一个程序,采用基数排序方法将一组英文单词按字典顺序排 列。假设单词均由小写字母或空格构成,最长的单词有 MaxLen 个 字母,用相关数据进行测试并输出各趟的排序结果。 用例&#…...

C++ list【常用接口、模拟实现等】

1. list的介绍及使用 1.1 list的介绍 1.list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。 2.list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前…...

12.面试题——Spring Boot

1.Spring Boot是什么? Spring Boot 是 Spring 开源组织下的子项目,是 Spring 组件一站式解决方案,主要是简化了使用 Spring 的难度,简省了繁重的配置,提供了各种启动器,开发者能快速上手。 2.为什么要用 …...

【前端VUE】npm i 出现版本错误等报错 简单直接解决命令

前端vue npm i 安装时出现 报错原因 在新版本的npm中,默认情况下,npm install遇到冲突的peerDependencies时将失败。 解决办法 使用--force或--legacy-peer-deps可解决这种情况。 --force 会无视冲突,并强制获取远端npm库资源&#xff0…...

精彩回顾 | 风丘科技亮相2024名古屋汽车工程博览会

2024年7月17日-19日,风丘科技联合德国IPETRONIK亮相日本名古屋汽车工程博览会。该展会面向汽车行业不同应用场景,包括新的eAxle、FCEV、ADAS、测试测量系统和ECU测试等相关技术,是一个专为活跃在汽车行业前线的工程师和研究人员举办的汽车技术…...

设计模式21-组合模式

设计模式21-组合模式(Composite Pattern) 写在前面 动机定义与结构定义结构主要类及其关系 C代码推导优缺点应用场景总结补充叶子节点不重载这三个方法叶子节点重载这三个方法结论 写在前面 数据结构模式 常常有一些组件在内部具有特定的数据结构。如何…...

如何选择深度学习的损失函数和激活函数

一概述 在深度学习中,损失函数(Loss Function)和激活函数(Activation Function)是两个至关重要的组件,它们共同影响着模型的训练效果和泛化能力。本文将简要介绍这两个概念,阐述选择它们的重要性…...

DATAX自定义KafkaWriter

因为datax目前不支持写入数据到kafka中,因此本文主要介绍如何基于DataX自定义KafkaWriter,用来同步数据到kafka中。本文偏向实战,datax插件开发理论宝典请参考官方文档: https://github.com/alibaba/DataX/blob/master/dataxPlug…...

Mybatis分页多表多条件查询

个人总结三种方式&#xff1a; Xml、queryWrapper、PageHelper第三方组件这三种方式进行查询&#xff1b; 方式一&#xff1a; xml中联表查询&#xff0c;在mapper中传参IPage<T>和条件Map&#xff08;这里用map装参数&#xff09;。 代码示例&#xff1a; Mapper层 M…...

SpringBoot快速入门(手动创建)

目录 案例&#xff1a;需求 步骤 1 创建Maven项目 2 导入SpringBoot起步依赖 3 定义Controller 4 编写引导类 案例&#xff1a;需求 搭建简单的SpringBoot工程&#xff0c;创建hello的类定义h1的方法&#xff0c;返回Hello SpringBoot! 步骤 1 创建Maven项目 大家&…...

C 408—《数据结构》算法题基础篇—数组(通俗易懂)

目录 Δ前言 一、数组的合并 0.题目&#xff1a; 1.算法设计思想&#xff1a; 2.C语言描述&#xff1a; 3.算法的时间和空间复杂度 : 二、数组元素的倒置 0.题目 : 1.算法设计思想 : 2.C语言描述 : 3.算法的时间和空间复杂度 : 三、数组中特定值元素的删除 0.题目 : …...

AI秘境-墨小黑奇遇记 - 初体验(一)

“怎么可能&#xff01;”墨小黑盯着屏幕上的代码&#xff0c;整个人都不好了。调试了三遍&#xff0c;翻了几遍书&#xff0c;结果还是不对。就像你以为自己早起赶车&#xff0c;结果发现闹钟根本没响一样崩溃。 这是他第一次真正接触人工智能实战任务——实现一个简单的感知…...

Android Wi-Fi 连接失败日志分析

1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分&#xff1a; 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析&#xff1a; CTR…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)

题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...

Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解

文章目录 一、开启慢查询日志&#xff0c;定位耗时SQL1.1 查看慢查询日志是否开启1.2 临时开启慢查询日志1.3 永久开启慢查询日志1.4 分析慢查询日志 二、使用EXPLAIN分析SQL执行计划2.1 EXPLAIN的基本使用2.2 EXPLAIN分析案例2.3 根据EXPLAIN结果优化SQL 三、使用SHOW PROFILE…...

2025年低延迟业务DDoS防护全攻略:高可用架构与实战方案

一、延迟敏感行业面临的DDoS攻击新挑战 2025年&#xff0c;金融交易、实时竞技游戏、工业物联网等低延迟业务成为DDoS攻击的首要目标。攻击呈现三大特征&#xff1a; AI驱动的自适应攻击&#xff1a;攻击流量模拟真实用户行为&#xff0c;差异率低至0.5%&#xff0c;传统规则引…...

计算机系统结构复习-名词解释2

1.定向&#xff1a;在某条指令产生计算结果之前&#xff0c;其他指令并不真正立即需要该计算结果&#xff0c;如果能够将该计算结果从其产生的地方直接送到其他指令中需要它的地方&#xff0c;那么就可以避免停顿。 2.多级存储层次&#xff1a;由若干个采用不同实现技术的存储…...

Cursor AI 账号纯净度维护与高效注册指南

Cursor AI 账号纯净度维护与高效注册指南&#xff1a;解决限制问题的实战方案 风车无限免费邮箱系统网页端使用说明|快速获取邮箱|cursor|windsurf|augment 问题背景 在成功解决 Cursor 环境配置问题后&#xff0c;许多开发者仍面临账号纯净度不足导致的限制问题。无论使用 16…...