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

JVM——JVM是怎么实现invokedynamic的?

JVM是怎么实现invokedynamic的?

在Java 7引入invokedynamic之前,Java虚拟机(JVM)在方法调用方面相对较为“僵化”。传统的Java方法调用主要依赖于invokestatic、invokespecial、invokevirtual和invokeinterface这四条指令,每条指令都明确绑定了目标方法的类名、方法名和方法描述符。这种绑定方式虽然稳定,但对于动态语言的支持却显得力不从心。动态语言强调“鸭子类型”(duck typing),即只要对象表现出某种行为,就认为它符合某种类型,而不必显式继承某个类或实现某个接口。为了打破这种限制,Java 7引入了invokedynamic指令,为JVM上的动态语言支持铺平了道路,同时也为Java自身的语言特性发展(如Lambda表达式)提供了强有力的支持。

invokedynamic指令的基本概念

invokedynamic指令的核心在于引入了“调用点”(CallSite)这一概念。调用点是一个抽象类,它将方法调用与目标方法的链接推迟到运行时进行。每个invokedynamic指令在执行时都会绑定一个调用点对象,该对象负责在运行时确定要调用的目标方法。调用点对象可以是ConstantCallSite(不可变调用点)、MutableCallSite(可变调用点)或VolatileCallSite(线程安全可变调用点)。通过调用点,JVM能够在运行时灵活地选择目标方法,从而支持动态类型语言的灵活调用机制。

import java.lang.invoke.*;
​
public class ConstantCallSiteDemo {public static void main(String[] args) throws Throwable {MethodHandles.Lookup lookup = MethodHandles.lookup();MethodType methodType = MethodType.methodType(void.class);MethodHandle methodHandle = lookup.findStatic(ConstantCallSiteDemo.class, "hello", methodType);CallSite callSite = new ConstantCallSite(methodHandle);((ConstantCallSite) callSite).dynamicInvoker().invokeExact();}
​public static void hello() {System.out.println("Hello, World!");}
}

invokedynamic的底层实现

(一)启动方法(Bootstrap Method)

当JVM第一次遇到invokedynamic指令时,它会执行该指令关联的启动方法。启动方法是一个特殊的静态方法,它负责创建并返回一个CallSite对象。启动方法的第一个参数必须是MethodHandles.Lookup对象,用于提供对类成员的访问权限;第二个参数是目标方法的名称(String类型);第三个参数是MethodType,表示目标方法的类型。除此之外,启动方法还可以接受其他参数,用于辅助生成CallSite对象。

import java.lang.invoke.*;
​
public class BootstrapDemo {public static void main(String[] args) throws Throwable {// 创建方法句柄MethodHandles.Lookup lookup = MethodHandles.lookup();MethodType type = MethodType.methodType(void.class);MethodHandle target = lookup.findStatic(BootstrapDemo.class, "hello", type);
​// 创建调用点CallSite callSite = new ConstantCallSite(target);
​// 获取动态调用的入口点MethodHandle dynamicInvoker = callSite.dynamicInvoker();
​// 动态调用dynamicInvoker.invokeExact();}
​public static void hello() {System.out.println("Hello, Invokedynamic!");}
}

启动方法返回一个CallSite对象,这个对象将与invokedynamic指令绑定,并在后续调用中直接使用。

(二)动态链接

调用点对象中的动态链接过程涉及到方法句柄(MethodHandle)的使用。方法句柄是一个强类型的引用,可以直接执行。它可以指向静态方法、实例方法、构造函数,甚至是字段的getter和setter方法(在方法句柄中表现为虚构方法)。与反射不同,方法句柄的权限检查在创建时完成,后续调用无需重复检查,因此性能更高。

import java.lang.invoke.*;
​
public class MethodHandleDemo {public static void main(String[] args) throws Throwable {// 创建方法句柄MethodHandles.Lookup lookup = MethodHandles.lookup();MethodType type = MethodType.methodType(void.class);MethodHandle methodHandle = lookup.findStatic(MethodHandleDemo.class, "hello", type);
​// 调用方法句柄methodHandle.invokeExact();}
​public static void hello() {System.out.println("Hello, Method Handle!");}
}

(三)Lambda 表达式与 invokedynamic

Lambda 表达式的出现是 Java 8 的一个重大更新,它允许开发者以更简洁的方式编写匿名类。Lambda 表达式的实现正是基于 invokedynamic 指令。当编译器遇到 Lambda 表达式时,会将其转换为一个函数式接口的实例。这个转换过程通过 invokedynamic 指令完成,编译器会生成一个 bootstrap 方法,该方法在运行时生成一个适配器类,实现对应的函数式接口。

例如,以下代码:

Comparator<String> comparator = (a, b) -> a.compareTo(b);

编译器会将其转换为类似如下的 invokedynamic 指令:

aload_1
invokedynamic #5, 0 // BootstrapMethod

对应的 bootstrap 方法会生成一个实现 Comparator 接口的适配器类,并返回该类的实例。

import java.lang.invoke.*;
​
public class LambdaBootstrap {public static void main(String[] args) throws Throwable {MethodHandles.Lookup lookup = MethodHandles.lookup();MethodHandle mh = lookup.findStatic(LambdaBootstrap.class, "lambdaImpl", MethodType.methodType(void.class, String.class));CallSite callSite = new ConstantCallSite(mh.asType(MethodType.methodType(void.class, Object.class)));((ConstantCallSite) callSite).dynamicInvoker().invokeExact("Hello, Lambda!");}
​private static void lambdaImpl(String s) {System.out.println(s);}
}

三、invokedynamic的性能分析

(一)方法句柄的性能

方法句柄的性能在某些场景下接近直接方法调用。通过将方法句柄存储在 final 静态变量中,即时编译器可以对其进行内联优化,从而消除方法句柄调用的开销。然而,如果方法句柄被频繁更新或无法被识别为常量,其性能可能接近反射调用,存在一定的性能开销。

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
​
public class MethodHandlePerformance {private static final MethodHandle MH;
​static {try {MethodHandles.Lookup lookup = MethodHandles.lookup();MethodType type = MethodType.methodType(void.class, int.class);MH = lookup.findStatic(MethodHandlePerformance.class, "target", type);} catch (Throwable e) {throw new RuntimeException(e);}}
​public static void main(String[] args) throws Throwable {long start = System.currentTimeMillis();for (int i = 0; i < 1000000000; i++) {MH.invokeExact(42);}System.out.println("MethodHandle: " + (System.currentTimeMillis() - start) + " ms");}
​public static void target(int i) {// 空方法}
}

(二)Lambda 表达式的性能

Lambda 表达式的性能在大多数情况下接近直接方法调用。对于未捕获变量的 Lambda 表达式,即时编译器可以内联其调用,性能与直接调用几乎无差异。而对于捕获变量的 Lambda 表达式,即时编译器的逃逸分析可以优化掉适配器实例的创建,使其性能接近未捕获变量的 Lambda 表达式。然而,在逃逸分析无法生效的情况下,可能会产生适配器实例的创建开销,性能会有所下降。

import java.util.function.IntConsumer;
​
public class LambdaPerformance {public static void main(String[] args {int x = 42;long start = System.currentTimeMillis();for (int i = 0; i < 1000000000; i++) {((IntConsumer) (j) -> {// 空实现}).accept(42);}System.out.println("Lambda: " + (System.currentTimeMillis() - start) + " ms");}
}

invokedynamic的实际应用与优势

(一)动态语言支持

invokedynamic为动态语言在JVM上的实现提供了基础支持。动态语言(如Groovy、JavaScript等)可以利用invokedynamic实现高效的动态方法调用,而无需通过反射或复杂的桥接代码。例如,在Groovy中,方法调用可以通过invokedynamic直接链接到目标方法,而无需显式的类型检查和方法查找,从而提高性能。

// Groovy示例
def hello(name) {println "Hello, $name!"
}hello "Invokedynamic"

(二)Java 8 的 Lambda 表达式

如前所述,Java 8 的 Lambda 表达式借助 invokedynamic 实现了简洁高效的语法糖。Lambda 表达式可以被转化为函数式接口的实例,而无需显式地实现接口。这不仅简化了代码,还提高了性能,因为 invokedynamic 允许即时编译器对 Lambda 表达式进行内联优化。

import java.util.function.Consumer;public class LambdaExample {public static void main(String[] args) {Consumer<String> consumer = (s) -> {System.out.println(s);};consumer.accept("Hello, Lambda!");}
}

(三)函数式编程

invokedynamic 支持函数式编程风格,使得 Java 开发者能够更方便地编写函数式代码。通过 Lambda 表达式和方法引用,开发者可以将行为(函数)作为参数传递给方法,或者将方法的结果作为函数返回。这种编程风格在处理集合操作(如流式 API)时尤为强大。

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;public class FunctionalExample {public static void main(String[] args) {List<String> names = Arrays.asList("Alice", "Bob", "Charlie");Consumer<String> printer = (name) -> System.out.println(name);names.forEach(printer);}
}

总结

invokedynamic 指令作为 Java 7 引入的一项革命性特性,为 JVM 带来了前所未有的灵活性和动态性。通过调用点(CallSite)和方法句柄(MethodHandle)的机制,invokedynamic 允许在运行时动态确定方法调用的目标,从而打破了传统方法调用的静态绑定限制。这不仅为动态语言在 JVM 上的高效实现铺平了道路,也为 Java 自身的语言发展注入了新的活力,使得诸如 Lambda 表达式等现代编程特性得以实现。在性能方面,尽管 invokedynamic 在某些复杂场景下可能存在一定的开销,但即时编译器的优化(如内联和逃逸分析)在大多数情况下能够使其性能接近甚至媲美直接方法调用。对于开发者而言,理解 invokedynamic 的工作原理有助于更好地利用 Java 8 及更高版本中的新特性,编写出更简洁、高效且具有函数式风格的代码,同时也为探索 JVM 上的动态语言世界打开了一扇大门。

相关文章:

JVM——JVM是怎么实现invokedynamic的?

JVM是怎么实现invokedynamic的&#xff1f; 在Java 7引入invokedynamic之前&#xff0c;Java虚拟机&#xff08;JVM&#xff09;在方法调用方面相对较为“僵化”。传统的Java方法调用主要依赖于invokestatic、invokespecial、invokevirtual和invokeinterface这四条指令&#x…...

使用 IDEA + Maven 搭建传统 Spring MVC 项目的详细步骤(非Spring Boot)

搭建Spring MVC项目 第一步&#xff1a;创建Maven项目第二步&#xff1a;配置pom.xml第三步&#xff1a;配置web.xml第四步&#xff1a;创建Spring配置文件第五步&#xff1a;创建控制器第六步&#xff1a;创建JSP视图第七步&#xff1a;配置Tomcat并运行目录结构常见问题解决与…...

洛谷 P1495:【模板】中国剩余定理(CRT)/ 曹冲养猪

【题目来源】 https://www.luogu.com.cn/problem/P1495 https://www.acwing.com/problem/content/225/ 【题目描述】 自从曹冲搞定了大象以后&#xff0c;曹操就开始捉摸让儿子干些事业&#xff0c;于是派他到中原养猪场养猪。可是曹冲满不高兴&#xff0c;于是在工作中马马虎…...

【iOS】 分类 拓展 关联对象

【iOS】 分类 拓展 关联对象 文章目录 【iOS】 分类 拓展 关联对象前言拓展分类分类与拓展的区别分类拓展关联对象哈希表(AssociationsHashMap) 大致工作流程setgetremove 关联对象的释放时机总结 前言 之前讲过有关于类对象的内容,这里学习一下有关于类的分类拓展和关联对象的…...

iview 老版本合并单元格

新版的iview中已经支持了合并单元格了&#xff0c;我的版本比较老&#xff0c;为&#xff1a;"iview": "^3.5.2"。暂不支持。记录一下别的大佬的方法。感觉思路比较活&#xff0c;正在这种思路需要在解决问题的过程中学习。 核心思路&#xff1a;通过rende…...

go语言实现用户管理系统

goweb实现用户管理系统 用户后台管理系统功能描述 登录功能 支持用户通过邮箱密码和密码进行登录。对输入的邮箱和密码进行验证&#xff0c;确保用户信息的正确性。登录成功后&#xff0c;更新用户的今日登录统计信息&#xff0c;并将用户信息存入会话&#xff08;cookie&am…...

普通IT的股票交易成长史--20250504实盘记录

声明&#xff1a;本文章的内容只是自己学习的总结&#xff0c;不构成投资建议。价格行为理论学习可参考简介中的几位&#xff0c;感谢他们的无私奉献。 送给自己的话&#xff1a; 仓位就是生命&#xff0c;绝对不能满仓&#xff01;&#xff01;&#xff01;&#xff01;&…...

SQL手工注入(DVWA)

手工SQL注入攻击的标准思路 Low等级 &#xff08;1&#xff09;判断是否存在注入 &#xff08;2&#xff09;猜解字段个数 &#xff08;3&#xff09;确定字段顺序 &#xff08;4&#xff09;获取当前数据库 &#xff08;5&#xff09;获取当前数据库中的表 &#xff08…...

【LLM】deepseek R1之GRPO训练笔记(持续更新)

note 相关框架对比&#xff1a; 需微调模型且资源有限 → Unsloth&#xff1b;本地隐私优先的小规模推理 → Ollama&#xff1b;复杂逻辑或多模态任务 → SGLang&#xff1b;高并发生产环境 → vLLM 微调SFT和GRPO是确实能学到新知识的四种格式&#xff08;messages、sharegpt…...

序列到序列学习

seq2seq 就是把一个句子翻译到另外一个句子。 机器翻译 给定一个源语言的句子&#xff0c;自动翻译成目标语言这两个句子可以有不同的长度 seq2seq 是一个 Encoder - Decoder 的架构 编码器是一个 RNN &#xff0c; 读取输入句子&#xff08;可以是双向&#xff09; 解码…...

去打印店怎么打印手机文件,网上打印平台怎么打印

在数字化时代&#xff0c;手机已成为我们存储和传输文件的重要工具。然而&#xff0c;当需要将手机中的文件转化为纸质文档时&#xff0c;许多人会面临选择&#xff1a;是前往线下打印店&#xff0c;还是利用线上打印平台&#xff1f;本文将为您解析这两种方式的优劣&#xff0…...

LeetCode每日一题5.4

1128. 等价多米诺骨牌对的数量 问题 问题分析 等价的定义为&#xff1a;两个骨牌 [a, b] 和 [c, d] 等价&#xff0c;当且仅当 (a c 且 b d) 或者 (a d 且 b c)。 思路 标准化骨牌表示&#xff1a; 为了方便比较&#xff0c;我们可以将每个骨牌 [a, b] 标准化为 [min(a…...

前端小练习————表白墙+猜数字小游戏

1&#xff0c;猜数字游戏 实现一个这个样式的 要猜的目标数字 点击重新开始游戏之后&#xff1a; 代码实现 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widt…...

五年级数学知识边界总结思考-上册

目录 一、背景二、过程1.小数乘法和除法小学五年级小数乘除法的知识点、由来、作用与意义解析**一、核心知识点梳理****二、知识点的由来****三、作用与意义****四、教学意义** **总结** 2.位置小学五年级“位置”知识点、由来、作用与意义解析**一、核心知识点梳理****二、知识…...

C与指针——内存操作与动态内存

1、内存常用操作 void* memcpy(void* dst,const void* src,size_t length); \\内存不允许重叠 void* memmove(void* dst,const void* src,size_t length); \\内存允许重叠 int memcmp(const void* dst,const void* src,size_t length); \\相等返回0 void* memset(void* dst,in…...

P3469 [POI 2008] BLO-Blockade

P3469 [POI 2008] BLO-Blockade 题目描述 B 城有 n n n 个城镇&#xff08;从 1 1 1 到 n n n 标号&#xff09;和 m m m 条双向道路。 每条道路连结两个不同的城镇&#xff0c;没有重复的道路&#xff0c;所有城镇连通。 把城镇看作节点&#xff0c;把道路看作边&…...

Linux网络编程 day3 五一结假

基本概念 三次握手 主动发起连接请求端&#xff0c;发送SYN标志位&#xff0c;请求建立连接。携带数据包包号、数据字节数(0)、滑动窗口大小。 被动接收连接请求端&#xff0c;发送ACK标志位&#xff0c;同时携带SYN请求标志位。携带序号、确认序号、数据包包号、数据字节数…...

解释一下NGINX的反向代理和正向代理的区别?

大家好&#xff0c;我是锋哥。今天分享关于【解释一下NGINX的反向代理和正向代理的区别?】面试题。希望对大家有帮助&#xff1b; 解释一下NGINX的反向代理和正向代理的区别? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 NGINX 作为一个高效的反向代理服务器&a…...

Coco AI 入驻 GitCode:打破数据孤岛,解锁智能协作新可能

在信息爆炸时代&#xff0c;企业正面临前所未有的挑战&#xff1a; 企业数据和信息分散&#xff0c;数据孤岛现象严重&#xff0c;员工往往浪费大量时间跨平台检索&#xff1b;跨部门协作困难&#xff0c;团队因信息隔阂导致项目延期&#xff1b;数据安全问题严峻&#xff0c;…...

【QT】QT中的网络编程(TCP 和 UDP通信)

QT中的网络编程&#xff08;TCP 和 UDP通信&#xff09; 1.tcp1.1 tcp通信1.1.1 相比linux中tcp通信:1.1.2 QT中的tcp通信: 1.2 tcp通信流程1.2.1 服务器流程&#xff1a;1.2.1.1 示例代码1.2.1.2 现象 1.2.2 客户端流程&#xff1a;1.2.2.1 示例代码1.2.2.2 现象&#xff1a; …...

个性化推荐:大数据引领电子商务精准营销新时代

个性化推荐:大数据引领电子商务精准营销新时代 引言 在电子商务的时代,个性化推荐系统已经成为提升用户体验、增强平台竞争力的重要技术。随着大数据技术的迅猛发展,传统的推荐方法已经无法满足用户日益增长的需求。为了精准地把握用户兴趣和消费倾向,商家们依赖大数据分析…...

【前端】【总复习】HTML

一、HTML&#xff08;结构&#xff09; HTML 是网页的骨架&#xff0c;主要负责网页的结构与语义表达&#xff0c;为 CSS 和 JavaScript 提供承载基础。 1.1 HTML 基本结构与语义化标签 1.1.1 HTML 基本结构 <!DOCTYPE html> <html lang"en"> <hea…...

Android 输入控件事件使用示例

一 前端 <EditTextandroid:id="@+id/editTextText2"android:layout_width="match_parent"android:layout_height="wrap_content"android:ems="10"android:inputType="text"android:text="Name" />二 后台代…...

JVM happens-before 原则有哪些?

理解Java Memory Model (JMM) 中的 happens-before 原则对于编写并发程序有很大帮助。 Happens-before 关系是 JMM 用来描述两个操作之间的内存可见性以及执行顺序的抽象概念。如果一个操作 A happens-before 另一个操作 B (记作 A hb B)&#xff0c;那么 JMM 向你保证&#x…...

Python实例题:Python获取NBA数据

目录 Python实例题 题目 方式一&#xff1a;使用网页爬虫获取数据 代码解释 get_nba_schedule 函数&#xff1a; 主程序&#xff1a; 方式二&#xff1a;使用专业 API 获取数据 代码解释 运行思路 方式一 方式二 注意事项 以下是完整的 doubaocanvas 代码块&#…...

【中间件】brpc_基础_remote_task_queue

文章目录 remote task queue1 简介2 核心功能2.1 任务提交与分发2.2 无锁或低锁设计2.3 与 bthread 深度集成2.4 流量控制与背压 3 关键实现机制3.1 数据结构3.2 任务提交接口3.3 任务窃取&#xff08;Work Stealing&#xff09;3.4 同步与唤醒 4 性能优化5 典型应用场景6 代码…...

React-router v7 第七章(导航)

导航 在React-router V7中&#xff0c;大致有四种导航方式&#xff1a; 使用Link组件 link使用NavLink组件 navlink使用编程式导航useNavigate usenavigate使用redirect重定向 redirect Link Link组件是一个用于导航到其他页面的组件&#xff0c;他会被渲染成一个<a>…...

Terraform 中的 external 数据块是什么?如何使用?

在 Terraform 中&#xff0c;external 数据块&#xff08;Data Block&#xff09; 是一种特殊的数据源&#xff0c;允许你通过调用外部程序或脚本获取动态数据&#xff0c;并将结果集成到 Terraform 配置中。它适用于需要从 Terraform 外部的系统或工具获取信息的场景。 一、e…...

打印Excel表格时单元格文字内容被下一行遮盖的解决方法

本文介绍在打印Excel表格文件时&#xff0c;单元格最后一行的文字内容被下一行单元格遮挡的解决方法。 最近&#xff0c;需要打印一个Excel表格文件。其中&#xff0c;已知对于表格中的单元格&#xff0c;都设置了自动换行&#xff0c;如下图所示。 并且&#xff0c;也都设置了…...

【Linux】命令行参数与环境变量

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;Linux 目录 前言 一、命令行参数 1. 什么是命令行参数 2. 命令行参数的作用 二、环境变量 1. 基本概念 2. 常见的环境变量 3. 环境变量相关操作 定义…...

Dify 完全指南(一):从零搭建开源大模型应用平台(Ollama/VLLM本地模型接入实战)》

文章目录 1. 相关资源2. 核心特性3. 安装与使用&#xff08;Docker Compose 部署&#xff09;3.1 部署Dify3.2 更新Dify3.3 重启Dify3.4 访问Dify 4. 接入本地模型4.1 接入 Ollama 本地模型4.1.1 步骤4.1.2 常见问题 4.2 接入 Vllm 本地模型 5. 进阶应用场景6. 总结 1. 相关资源…...

民法学学习笔记(个人向) Part.3

民法学学习笔记&#xff08;个人向&#xff09; Part.3 8. 诉讼时效&#x1f338; 概念&#xff1a; 是指权利主体在法定期间内不行使权利&#xff0c;则债务人享有抗辩权&#xff0c;可以导致权利人无法胜诉的法律制度&#xff08;有权你不用&#xff0c;别人就有话说了&#…...

C# 方法(返回值、返回语句和void方法)

本章内容: 方法的结构 方法体内部的代码执行 局部变量 局部常量 控制流 方法调用 返回值 返回语句和void方法 局部函数 参数 值参数 引用参数 引用类型作为值参数和引用参数 输出参数 参数数组 参数类型总结 方法重载 命名参数 可选参数 栈帧 递归 返回值 方法可以向调用代码返…...

打电话玩手机检测数据集VOC+YOLO格式8061张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;8061 标注数量(xml文件个数)&#xff1a;8061 标注数量(txt文件个数)&#xff1a;8061 …...

详解如何压测RocketMQ

目录 1.如何设计压测 2.压测工具 3.硬件配置 4.写代码压测 5.自带压测脚本 1.如何设计压测 二八定律法则&#xff1a;按业务峰值的 120% 设计压测目标&#xff08;若线上峰值1000TPS&#xff0c;压测目标至少1200TPS&#xff09; 关注三个指标 吞吐量&#xff08;TPS&…...

实验三 触发器及基本时序电路

1.触发器的分类&#xff1f;各自的特点是什么&#xff1f; 1 、 D 触发器 特点&#xff1a;只有一个数据输入端 D &#xff0c;在时钟脉冲的触发沿&#xff0c;输出 Q 的状态跟随输入端 D 的 状态变化&#xff0c;即 &#xff0c;功能直观&#xff0c;利于理解和感受…...

双列集合——map集合和三种遍历方式

双列集合的特点 键和值一一对应&#xff0c;每个键只能对应自己的值 一个键和值整体称为键值对或键值对对象&#xff0c;java中叫做entry对象。 map常见的api map接口中定义了双列集合所有的共性方法&#xff0c;下面三个实现类就没有什么额外新的方法要学习了。 map接口…...

WebRTC 服务器之Janus视频会议插件信令交互

1.基础知识回顾 WebRTC 服务器之Janus概述和环境搭建-CSDN博客 WebRTC 服务器之Janus架构分析-CSDN博客 2.插件使用流程 我们要使⽤janus的功能时&#xff0c;通常要执⾏以下操作&#xff1a; 1. 在你的⽹⻚引入 Janus.js 库&#xff0c;即是包含janus.js&#xff1b; <…...

LabVIEW温控系统热敏电阻滞后问题

在 LabVIEW 构建的温控系统中&#xff0c;热敏电阻因热时间常数大&#xff08;2 秒左右&#xff09;产生的滞后效应&#xff0c;致使控温出现超调与波动。在不更换传感器的前提下&#xff0c;可从算法优化、硬件调整和系统设计等维度着手解决。 ​ 一、算法优化​ 1. 改进 PI…...

【Unity】使用XLua进行热修复

准备工作&#xff1a; &#xff08;1&#xff09;将XLua的Tool拖入Asset &#xff08;2&#xff09;配置热修复 &#xff08;3&#xff09;运行Genrate Code &#xff08;4&#xff09;运行Hotfix Inject In Editor 编写脚本&#xff08;注意类上带有[Hotfix]&#xff09; [Hot…...

GateWay使用

首先创建一个网关服务&#xff0c;添加对应的依赖 <dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><dependency><groupId&…...

如何使用责任链模式优雅实现功能(滴滴司机、家政服务、请假审批等)

在企业级开发中&#xff0c;我们经常会遇到一系列有先后顺序、逐步处理的逻辑链路&#xff0c;例如请假审批、报销审批、日志处理、事件处理、滴滴司机接单流程等。这些场景非常适合使用 责任链模式&#xff08;Chain of Responsibility Pattern&#xff09; 来优雅地实现。 本…...

opencv的contours

1.哪里来的contours&#xff1a; 我们常常用到这一句&#xff1a; contours, hierarchy cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 输出的contours的是一个tuple类型的&#xff1a; 1.它的len&#xff08;&#xff09;就是contour的个数 2.每一…...

使用 OpenCV 和 Dlib实现轮廓绘制

文章目录 引言1.准备工作2.代码解析2.1 导入必要的库2.2 定义绘制直线函数2.3 定义绘制凸包函数2.4 加载图像和模型2.5 关键点检测与绘制2.6 显示结果 3.68个关键点索引说明4.应用场景5.优化建议6. 结语 引言 人脸关键点检测是计算机视觉中的重要任务&#xff0c;广泛应用于人…...

学习黑客Linux 命令

在操作下面的闯关题之前&#xff0c;给下学习资料 一图速览&#xff1a;20 条命令及练习手册 #命令 & 常用参数关键作用典型练习1ls -alh列文件&#xff08;含隐藏 & 人类可读大小&#xff09;(数字海洋)在 $HOME 统计目录数2cd / pwd切换、显示路径cd /tmp &&a…...

探秘 RocketMQ 的 DLedgerServer:MemberState 的技术解析与深度剖析

在 RocketMQ 构建高可靠、强一致性消息系统的架构中&#xff0c;DLedgerServer 扮演着举足轻重的角色&#xff0c;而 MemberState 作为 DLedgerServer 内部用于描述节点状态的核心类&#xff0c;更是整个分布式日志模块稳定运行的关键。深入理解 MemberState 的设计理念、功能特…...

【计算机网络】HTTP中GET和POST的区别是什么?

从以下几个方面去说明&#xff1a; 1.定义 2.参数传递方式 3.安全性 4.幂等性 1.定义&#xff1a; GET&#xff1a; 获取资源&#xff0c;通常请求数据而不改变服务器的状态。POST&#xff1a; 提交数据到服务器&#xff0c;通常会改变服务器的状态或副作用(如创建或更新资源…...

C++负载均衡远程调用学习之Agent代理模块基础构建

目录 1.课程复习 2.Lars-lbAgentV0.1-udpserver启动 3.Lars-lbAgentV0.1-dns-reporter-client-thread启动 4.Lars-lbAgentV0.1-dns-client实现 5.Lars-lbAgentV0.1-dns-client编译错误修正 6.Lars-lbAgentV0.1-reporter_client实现 1.课程复习 ### 11.2 完成Lars Reactor…...

游戏开发的TypeScript(4)TypeScript 的一些内置函数

在 TypeScript 中&#xff0c;内置函数分为两类&#xff1a;JavaScript 原生函数&#xff08;TypeScript 继承&#xff09;和TypeScript 特有函数&#xff08;类型系统相关&#xff09;。以下是详细分类介绍&#xff1a; 一、JavaScript 原生函数 TypeScript 继承了所有 Java…...

软考 系统架构设计师系列知识点之杂项集萃(52)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之杂项集萃&#xff08;51&#xff09; 第82题 以下关于系统性能的叙述中&#xff0c;不正确的是&#xff08;&#xff09;。 A. 常见的Web服务器性能评估方法有基准测试、压力测试和可靠性测试 B. 评价Web服务器的主…...