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

探索 JNI - Rust 与 Java 互调实战

真正的救赎,并非厮杀后的胜利,而是能在苦难之中,找到生的力量和内心的安宁。

——加缪Albert Camus

一、Rust + Java = ? 

Java 和 Rust 是两种现代编程语言,各自具有独特的优势,适用于不同的应用场景。

1、Java 的优势

  1. 跨平台性:Java 的“写一次,运行到处”的理念使得它能够在各种操作系统上运行,只要有 JVM(Java Virtual Machine)支持即可。
  2. 丰富的生态系统:Java 拥有庞大的标准库和第三方库生态系统,涵盖了几乎所有的开发需求,从 web 开发、数据库访问到大数据处理等。
  3. 成熟的工具链:Java 具有成熟的开发工具链,包括 IDE(如 IntelliJ IDEA、Eclipse)、构建工具(如 Maven、Gradle)和调试工具,这些工具极大地提高了开发效率。
  4. 强大的社区支持:Java 社区非常活跃,有大量的开源项目、文档和教程,可以帮助开发者快速解决问题。
  5. 垃圾回收机制:Java 的自动垃圾回收机制简化了内存管理,减少了内存泄漏和其他内存相关错误的风险。
  6. 企业级应用:Java 在企业级应用开发中占据重要地位,特别是在金融、电信和大型分布式系统中,Java 被广泛使用。
  7. 多线程支持:Java 提供了强大的多线程支持,方便开发并发和并行程序。

2、Rust 的优势

  1. 内存安全:Rust 的所有权系统和借用检查器在编译时保证了内存安全,防止了常见的内存错误,如空指针引用、悬挂指针和缓冲区溢出。
  2. 高性能:Rust 生成的代码接近 C 和 C++ 的性能,同时提供了更高的安全性和更少的运行时开销。
  3. 无畏并发:Rust 的所有权模型使得编写并发代码更加安全和简单,避免了数据竞争和死锁等问题。
  4. 现代语言特性:Rust 支持模式匹配、闭包、泛型、trait 等现代编程语言特性,使得代码更加简洁和可维护。
  5. 强类型系统:Rust 的强类型系统在编译时捕获更多的错误,提高了代码的可靠性和可维护性。
  6. 零成本抽象:Rust 提供了高层次的抽象,但这些抽象在编译后不会引入额外的运行时开销,实现了所谓的“零成本抽象”。
  7. 良好的文档和工具链:Rust 提供了优秀的文档和工具链,包括 Cargo(包管理和构建工具)、rustfmt(代码格式化工具)和 Clippy(代码审查工具),这些工具极大地提高了开发体验。
  8. 嵌入式和系统编程:Rust 非常适合嵌入式和系统级编程,能够直接操作硬件,同时保持高安全性和性能。

3、Rust + Java 的应用思路

Java 和 Rust 各有其独特的优势,适用于不同的应用场景:

  • Java 适合需要跨平台兼容性、丰富生态系统和成熟工具链的企业级应用和大型分布式系统。
  • Rust 则适合需要高性能、内存安全和并发控制的系统级编程、嵌入式开发以及对性能和安全性要求极高的应用。

通过结合 Java 和 Rust 的优势,可以在实际项目中实现更高效、安全和功能强大的解决方案。例如,可以使用 Java 实现业务逻辑和用户界面,而使用 Rust 实现性能关键的底层模块和系统组件。

4、应用场景

  1. 性能关键模块:在 Java 应用中,某些性能关键的部分可以用 Rust 编写,以提高执行效率。例如,计算密集型算法、数据处理或图像处理等任务可以用 Rust 实现,然后通过 JNI(Java Native Interface)调用这些 Rust 函数。
  2. 内存安全和并发控制:Rust 的所有权机制和借用检查器可以帮助避免内存泄漏和数据竞争问题。在需要严格内存管理和并发控制的场景下,可以用 Rust 编写核心逻辑,并通过 FFI(Foreign Function Interface)与 Java 进行交互。
  3. 系统级编程:对于需要直接操作系统资源或硬件的功能,例如文件系统操作、网络通信或设备驱动程序,可以用 Rust 编写这些底层代码,然后通过 JNI 或 JNA(Java Native Access)与 Java 应用进行交互。
  4. 跨平台开发:Rust 可以编译成多种平台的二进制文件,而 Java 本身具有良好的跨平台特性。在需要支持多种操作系统的应用中,可以利用 Rust 编写跨平台的库,并通过 Java 调用这些库,从而实现跨平台兼容性。
  5. 安全性要求高的应用:在金融、医疗等对安全性要求极高的领域,可以用 Rust 编写关键的安全模块,如加密算法、身份验证等,然后通过 JNI 与 Java 应用集成,以确保系统的整体安全性。
  6. 微服务架构:在微服务架构中,不同的服务可以用不同的语言实现。如果某些微服务用 Rust 编写,而其他服务用 Java 编写,可以通过 RESTful API 或 gRPC 等方式进行通信,实现互操作。
  7. 游戏开发:游戏引擎或性能要求高的游戏逻辑可以用 Rust 编写,而游戏的业务逻辑、界面等可以用 Java 编写,通过 JNI 调用 Rust 实现高效的游戏运行。

二、JNI:实现 Rust 与 Java 互调的桥梁

1、如何理解 JNI

Java Native Interface(JNI)是 Java 平台的一部分,它允许 Java 代码与用其他编程语言(如 C、C++ )编写的本地代码进行交互。JNI 的角色可以理解为桥梁或接口,连接了 Java 虚拟机(JVM)和本地代码库,使得两者能够相互调用和通信。

跨语言调用:JNI 使得 Java 程序能够调用本地代码中的函数,也使得本地代码能够调用 Java 方法。这种双向调用能力使得开发者可以在 Java 应用中利用其他语言的特性和性能优势。

性能优化:在某些情况下,Java 代码可能无法提供足够的性能,例如在处理大量数据或执行复杂计算时。通过 JNI,可以将这些性能关键的部分用更高效的语言(如 C、C++)实现,然后在 Java 中调用,从而提升整体应用的性能。

访问底层系统资源:Java 本身是一个高级语言,通常不直接提供对底层系统资源(如硬件设备、操作系统 API)的访问。通过 JNI,Java 程序可以调用本地代码来访问这些底层资源,实现系统级编程。

复用现有库和代码:很多已有的库和代码是用其他语言编写的。通过 JNI,Java 程序可以直接调用这些现有的库,而无需重新实现,从而节省开发时间和成本。

内存管理:JNI 提供了一套机制来管理 Java 和本地代码之间的内存交互。虽然 Java 有自动垃圾回收机制,但本地代码需要手动管理内存。JNI 提供了必要的工具和方法来确保内存安全和有效管理。

错误处理和调试:JNI 提供了一些工具和方法来处理和调试 Java 与本地代码之间的交互问题。例如,通过 JNI 可以捕获和处理本地代码中的异常,并将其转换为 Java 异常,从而在 Java 层面进行处理。

平台独立性:尽管 JNI 允许调用本地代码,这些本地代码往往是平台相关的。然而,JNI 本身作为一个标准接口,使得开发者可以编写跨平台的 Java 代码,同时针对不同的平台编写相应的本地代码库,从而实现一定程度的跨平台兼容性。

总结来说,JNI 的角色是充当 Java 和本地代码之间的桥梁,提供了一种机制,使得 Java 应用能够利用其他语言的特性和性能优势,同时保持一定的灵活性和扩展性。JNI 既然是 C 语言接口,那么理论上支持 C ABI 的语言都可以和 Java 语言互相调用,Rust 就是其中之一。

关于 JNI 的历史背景以及更详细的介绍可以参考 官方文档

2、JNI 相关概念

Java 本地方法:在 Java 中声明但由本地代码实现的方法。

JNI 环境指针 (JNIEnv *):用于访问 JNI 提供的函数和 Java 虚拟机(JVM)的接口。

本地库:包含本地方法实现的共享库或动态链接库(如 .dll.so 文件)。

Java 本地方法(Native Method)、JNI 环境指针(JNIEnv *)和本地库在一起工作时,通常遵循以下流程:

  1. 声明本地方法
    在 Java 代码中,你需要声明一个本地方法。这个方法使用 native 关键字,并且没有方法体。例如:

    public class MyClass {public native void myNativeMethod();static {System.loadLibrary("MyNativeLib");}
    }

    System.loadLibrary("MyNativeLib") 用于加载包含本地方法实现的本地库。

  2. 生成头文件
    使用 javac 编译 Java 文件,然后使用 javah 工具生成对应的 C/C++ 头文件。例如:

    javac MyClass.java
    javah -jni MyClass

    这会生成一个名为 MyClass.h 的头文件,其中包含 JNI 函数签名。

  3. 实现本地方法
    在生成的头文件基础上,用 C 或 C++ 实现本地方法。例如:

    #include <jni.h>
    #include "MyClass.h"JNIEXPORT void JNICALL Java_MyClass_myNativeMethod(JNIEnv *env, jobject obj) {// 本地方法的实现
    }
  4. 编译本地库
    将实现本地方法的 C/C++ 代码编译成共享库或动态链接库。例如,在 Linux 上可以使用 gcc

    gcc -shared -o libMyNativeLib.so -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux MyClass.c

    在 Windows 上可以使用类似的命令生成 .dll 文件。

  5. 加载本地库
    当 Java 程序运行并调用 System.loadLibrary("MyNativeLib") 时,JVM 会加载指定的本地库。

  6. 调用本地方法
    当 Java 代码调用 myNativeMethod() 时,JVM 通过 JNI 调用对应的本地方法实现。此时,JNI 环境指针 (JNIEnv *) 被传递给本地方法,允许它访问 JNI 提供的函数和 JVM 的接口。

  7. 执行本地代码
    本地方法在本地库中执行,可以进行各种操作,包括调用底层系统 API、处理硬件设备、执行高性能计算等。

  8. 返回结果
    如果本地方法有返回值,它会将结果返回给 Java 层。如果发生异常,本地方法可以通过 JNIEnv * 抛出 Java 异常。

整个流程如下图所示:

Java 层:MyClass.java (声明本地方法)|v编译 -> MyClass.class|v生成头文件 -> MyClass.h|v
C/C++ 层:MyClass.c (实现本地方法)|v编译 -> libMyNativeLib.so / MyNativeLib.dll|v
Java 层:System.loadLibrary("MyNativeLib")|v调用本地方法 -> JNI 调用 -> 执行本地代码|v返回结果 / 抛出异常

通过这种方式,Java 程序可以与本地代码进行交互,实现更底层的功能或优化性能。

3、JNI 的 Rust 绑定

在 Rust 中和 Java 互相调用,可以使用原始的 JNI 接口,也就是自己声明 JNI 的 C 函数原型,在Rust 里按照 C 的方式去调用,但这样写起来会很繁琐,而且都是 unsafe 的操作。不过 Rust 社区里已经有人基于原始的 JNI 接口,封装好了一套 safe 的接口,crate 的名字就叫 jni ,用这个库来开发就方便多了。

三、互调示例

Step1、定义一个异步耗时操作 CostTimeOption

Step2、Java 端调用 Rust 端,由 Rust 端执行一个异步耗时操作 CostTimeOption

Step3、Rust 端调用 Java 端报告操作已消耗时长和进度

Step 1、创建一个 Maven 项目

import java.time.Duration;
import java.time.LocalDateTime;/*** @version: V1.0* @author: 余衫马* @description: MyJobAgent* @data: 2024-11-12 15:58**/
public class MyJobAgent {/*** 声明一个本地方法* 将 MyJobAgent 实例作为参数传递给 Rust 端*/private static native void runCostTimeFuncAsync(MyJobAgent callback);/*** 开始执行时间*/private static LocalDateTime startDatetime;// 用于加载包含本地方法实现的本地库。static {System.loadLibrary("rust_jni_bingding_demo");}public static void main(String[] args) {startDatetime = LocalDateTime.now();runCostTimeFuncAsync(new MyJobAgent());}/*** 回调方法,由 Rust 端回调 progress 进度*/public void asyncCallback(float progress) {// 计算两个时间点之间的 DurationDuration duration = Duration.between(startDatetime, LocalDateTime.now());// 获取分钟、秒和毫秒long minutes = duration.toMinutes();long seconds = duration.getSeconds();long millis = duration.toMillis();System.out.printf("当前进度:%f,已耗时:%d 分 %d 秒 %d 毫秒\n", progress, minutes, seconds, millis);}
}

我们创建了一个 MyJobAgent  代理工作类,声明了一个本地方法 runCostTimeFuncAsync ,参数是 MyJobAgent 实例是为了让 Rust 端能调用该实例的回调方法 asyncCallback,

private static native void runCostTimeFuncAsync(MyJobAgent callback);

 而回调方法 asyncCallback 需要接收一个参数 progress 输出进度,并计算目前已耗时多久,

    /*** 回调方法,由 Rust 端回调 progress 进度*/public void asyncCallback(float progress) {// 计算两个时间点之间的 DurationDuration duration = Duration.between(startDatetime, LocalDateTime.now());// 获取分钟、秒和毫秒long minutes = duration.toMinutes();long seconds = duration.getSeconds();long millis = duration.toMillis();System.out.printf("当前进度:%f,已耗时:%d 分 %d 秒 %d 毫秒", progress, minutes, seconds, millis);}

Linux 下的动态库 librust_jni_bingding_demo.so 只需要填 rust_jni_bingding_demo,

  // 用于加载包含本地方法实现的本地库。static {System.loadLibrary("rust_jni_bingding_demo");}

Step 2、创建一个 Rust 项目

cargo new  rust_jni_bingding_demo --lib

修改 Cargo.toml,添加 Rust jni 绑定库,并且设置 crate_type = ["cdylib"]

[dependencies]
jni = "0.21.1"[lib]
crate_type = ["cdylib"]

修改 lib.rs,

use std::sync::mpsc; // 引入多生产者单消费者通道模块
use std::thread::{self}; // 引入线程模块
use std::time::Duration; // 引入时间模块use jni::objects::*; // 引入JNI对象模块
use jni::sys::jfloat; // 引入JNI浮点数类型
use jni::JNIEnv; // 引入JNI环境模块// 定义一个外部函数,供Java调用
#[no_mangle]
pub extern "system" fn Java_MyJobAgent_runCostTimeFuncAsync<'local>(mut env: JNIEnv<'local>, // JNI环境参数_class: JClass<'local>, // 调用该方法的Java类callback: JObject<'local>, // 回调对象
) {// 获取当前Java虚拟机实例let jvm = env.get_java_vm().unwrap();// 创建全局引用,以便在其他线程中使用回调对象let mycallback = env.new_global_ref(callback).unwrap();// 创建一个多生产者单消费者通道let (tx, rx) = mpsc::channel();// 启动一个新线程let _ = thread::spawn(move || {// 在线程中发送一个信号,表示线程已经启动tx.send(()).unwrap();// 将当前线程附加到JVMlet mut myenv = jvm.attach_current_thread().unwrap();// 模拟一个耗时操作,并定期调用回调函数报告进度for i in 0..100 {let progress = i as jfloat; // 将进度转换为JNI浮点数类型// 调用回调方法,将进度传递给Java层 // 函数签名为(float)voidmyenv.call_method(&mycallback, "asyncCallback", "(F)V", &[progress.into()]).unwrap();// 休眠100毫秒,模拟耗时操作thread::sleep(Duration::from_millis(100));}});// 接收线程启动信号,确保线程已成功启动rx.recv().unwrap();
}

代码解析:

  1. 引入必要的模块:首先引入了标准库中的mpscthreadtime模块,以及JNI相关的模块。
  2. 定义外部函数:定义了一个外部函数Java_MyJobAgent_runCostTimeFuncAsync,这个函数将被Java代码调用。
  3. 获取JVM实例:通过env.get_java_vm()获取当前的Java虚拟机实例。
  4. 创建全局引用:将回调对象创建为全局引用,以便在线程中使用。
  5. 创建通道:创建一个多生产者单消费者通道,用于线程间通信。
  6. 启动新线程:启动一个新线程,在新线程中执行耗时操作。
  7. 附加线程到JVM:将新线程附加到JVM,以便在新线程中调用Java方法。
  8. 模拟耗时操作:在循环中模拟一个耗时操作,每次循环都会调用一次回调方法,将当前进度传递给Java层,并休眠100毫秒。
  9. 接收线程启动信号:主线程等待接收子线程发送的启动信号,确保子线程已成功启动。

这样,通过上述步骤,我们实现了一个异步任务,并在任务执行过程中定期向Java层报告进度。

Step 3、编译代码

编译 Rust 库

cargo build

我这里用的 linux 系统,动态库文件名为 librust_jni_bingding_demo.so,如果是 Windows 系统,文件名为 librust_jni_bingding_demo.dll,

编译 Java 代码

修改 pom.xml,在构建配置文件中指定主类,

<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>3.2.0</version><configuration><archive><manifest><addDefaultImplementationEntries>true</addDefaultImplementationEntries><mainClass>MyJobAgent</mainClass></manifest></archive></configuration></plugin></plugins></build>

然后执行 maven 打包指令, 

mvn package

在 target 目录下生成 classes 字节码文件与 RustJniDemo-1.0-SNAPSHOT.jar 。 

Step 4、运行效果

这里使用的是 Open JDK8,

(base) sam@sam-PC:~/AwesomeWorkSpace/RustStudy/jni/rust_jni_bingding_demo$ java -version
openjdk version "1.8.0_212"
OpenJDK Runtime Environment (build 1.8.0_212-8u212-b01-1~deb9u1-b01)
OpenJDK 64-Bit Server VM (build 25.212-b01, mixed mode)
# 临时添加环境变量,否则会报错找不到库文件
# export PATH=$PATH:~/AwesomeWorkSpace/RustStudy/rust_jni_binding_demo/target/debug
java -Djava.library.path=target/debug -classpath target/classes MyJobAgent
# 或者直接跑 jar 包
java -Djava.library.path=target/debug -jar target/RustJniDemo-1.0-SNAPSHOT.jar 
  1. -Djava.library.path=target/debug:这是一个系统属性设置,-D选项用于定义系统属性。在这里,java.library.path属性被设置为target/debug,这通常是用来指定本地库(如JNI库)的搜索路径。

  2. -classpath target/classes:这是指定类路径的选项,-classpath-cp用于告诉JVM在哪里可以找到用户定义的类和包。在这个例子中,类路径被设置为target/classes,这意味着JVM会在target/classes目录下查找需要的类文件。

  3. MyJobAgent:这是要运行的主类的名称。这个类应该包含一个public static void main(String[] args)方法,这是Java应用程序的入口点。

四、总结

通过以上示例,我们成功实现了 Rust 与 Java 的互调。利用 JNI 技术,可以充分发挥 Rust 的性能优势,同时保持 Java 的跨平台特性。这种技术组合适用于对性能要求较高的应用场景,如图像处理、数据分析和系统级编程等。

参考资料

Rust与Java交互-JNI模块编写-实践总结 - Rust语言中文社区

Leveraging Rust in our high-performance Java database

https://docs.oracle.com/javase/8/docs/technotes/guides/jni/

jni - Rust

https://github.com/jni-rs/jni-rs

相关文章:

探索 JNI - Rust 与 Java 互调实战

真正的救赎&#xff0c;并非厮杀后的胜利&#xff0c;而是能在苦难之中&#xff0c;找到生的力量和内心的安宁。 ——加缪Albert Camus 一、Rust Java &#xff1f; Java 和 Rust 是两种现代编程语言&#xff0c;各自具有独特的优势&#xff0c;适用于不同的应用场景。 1、…...

网络安全-Linux基础(bash脚本)

文章目录 bash脚本编写基础使用的脚本解析器/bin/bash&#xff08;声明&#xff09;bash脚本需要拥有执行权限bash脚本语法输入与输出函数的封装条件判断语句条件符号 循环语句模块化编程 Linux进程操作查看寻找进程终止进程暂停与恢复进程后台运行 bash脚本编写系统内存资源占…...

Lucene 和 Elasticsearch 中更好的二进制量化 (BBQ)

作者&#xff1a;来自 Elastic Benjamin Trent Lucene 和 Elasticsearch 中更好的二进制量化 (BBQ)。 嵌入模型输出 float32 向量&#xff0c;通常对于高效处理和实际应用来说太大。Elasticsearch 支持 int8 标量量化&#xff0c;以减小向量大小&#xff0c;同时保持性能。其他…...

jmeter基础05_第1个http请求

本节课使用网站“httpbin.org”进行基础的http请求全流程。 请求获取httpbin.org的首页&#xff1a; 请求方法&#xff1a;GET URL&#xff1a;http://httpbin.org 参数&#xff1a;无 1、操作步骤 ① 打开jmeter&#xff1a;命令行窗口输入“jmeter”并回车。 ② 添加线程组…...

C++builder中的人工智能(25):AI中的C++多线程std::thread

主要是为Ai算法中要使用到C的多线程&#xff0c;这是使用C11中的多线程std::thread。 在现代数学、物理和计算机科学中&#xff0c;优化和加速应用程序开发在编程中非常重要&#xff0c;以加快计算速度。多核心CPU和GPU通过核心和晶体管的数量得到了高度发展&#xff0c;为当今…...

RestSharp基本使用方法

关于RestSharp RestSharp is a library that allows you to make REST and HTTP calls in .NET applications. It supports serialization, parameters, async functions, and more. RestSharp是C#的一个WepApi库&#xff0c;支持通用的Web接口处理&#xff0c;支持序列化、参数…...

MySQL与Oracle对比及区别

一、比较 1、MySQL的特点 性能卓越&#xff0c;服务稳定&#xff0c;很少出现异常宕机&#xff1b; 开放源代码无版本制约&#xff0c;自主性及使用成本低&#xff1b; 历史悠久&#xff0c;社区和用户非常活跃&#xff0c;遇到问题及时寻求帮助&#xff1b; 软件体积小&#…...

NCC前端调用查询弹框

系统自带的查询模板 弹框 调启使用默认的 查询模板 是在 单据模板的 列表模板中&#xff0c;有个查询区域 &#xff0c;查询区域就是查询模板内容如果在列表页做客开 新增按钮 调启查询模板 无问题&#xff0c;但是目前需求是需要再卡片页面下调启系统标准的调启模板代码 //调…...

【高中生讲机器学习】25. AdaBoost 算法详解+推导来啦!

创建时间&#xff1a;2024-11-08 首发时间&#xff1a;2024-11-13 最后编辑时间&#xff1a;2024-11-13 作者&#xff1a;Geeker_LStar 你好呀~这里是 Geeker_LStar 的人工智能学习专栏&#xff0c;很高兴遇见你~ 我是 Geeker_LStar&#xff0c;一名高一学生&#xff0c;热爱计…...

第三十七章 Vue之编程式导航及跳转传参

目录 一、编程式导航跳转方式 1.1. path 路径跳转 1.1.1. 使用方式 1.1.2. 完整代码 1.1.2.1. main.js 1.1.2.2. App.vue 1.1.2.3. index.js 1.1.2.4. Home.vue 1.1.2.5. Search.vue 1.2. name 命名路由跳转 1.2.1. 使用方式 1.2.2. 完整代码 1.2.2.1. main.js 1…...

vue 版本升级

Vue 3.4 升级了组件产值方式 v-model &#xff0c;果断升级玩玩&#xff0c;记录一下升级过程 我的原Vue版本是3.2.13 升级到目前最新3.5.12 1. npm add vuelatest 2. npm add -g vue/clilatest 安装完成后记得查看是否有如下警告 这个警告是说eslint-plugin-vue package…...

探索Copier:Python项目模板的革命者

文章目录 **探索Copier&#xff1a;Python项目模板的革命者**1. 背景介绍&#xff1a;为何Copier成为新宠&#xff1f;2. Copier是什么&#xff1f;3. 如何安装Copier&#xff1f;4. 简单库函数使用方法4.1 创建模板4.2 从Git URL创建项目4.3 使用快捷方式4.4 动态替换文本4.5 …...

云原生后端深度解析

云原生后端 云原生后端是指专门为云计算环境设计的软件架构和服务。它强调了应用程序的设计、开发、部署和运维的方式&#xff0c;以充分利用云平台提供的弹性、可伸缩性和自动化能力。云原生技术主要包括容器化、微服务、不可变基础设施、声明式APIs等核心概念。下面是对这些…...

本地 SSL 证书生成神器,自己创建SSL

本地 SSL 证书生成神器,自己创建SSL 在本地环境中配置HTTPS一直以来是开发者的痛点,手动创建SSL证书、配置信任存储不仅繁琐,还容易出错。今天给大家介绍一个开源神器——mkcert!它能让你快速生成本地受信任的SSL/TLS证书,轻松打造安全的HTTPS开发环境,成为许多开发者的首…...

HCIP-快速生成树RSTP

一、RSTP是什么 STP&#xff08;Spanning Tree Protocol &#xff09;是生成树协议的英文缩写。该协议可应用于环路网络&#xff0c;通过一定的算法实现路径冗余&#xff0c;同时将环路网络修剪成无环路的树型网络&#xff0c;从而避免报文在环路网络中的增生和无限循环。 RS…...

企业级RAG(检索增强生成)系统构建研究

— 摘要 检索增强生成&#xff08;Retrieval-Augmented Generation&#xff0c;RAG&#xff09;技术已经成为企业在知识管理、信息检索和智能问答等应用中的重要手段。本文将从RAG系统的现状、方法论、实践案例、成本分析、实施挑战及应对策略等方面&#xff0c;探讨企业如何…...

MATLAB基础应用精讲-【数模应用】Google Caffeine算法

目录 前言 算法原理 Caffeine算法的背景和优势 什么是Caffeine算法 Caffeine算法的工作原理 常见的缓存数据淘汰算法 FIFO LRU LFU W-TinyLFU Caffeine W-TinyLFU 实现 元素驱逐 元素访问 Caffeine 的四种缓存添加策略 1. 手动加载 2. 自动加载 3. 手动异步加载…...

第十九届中国国际中小企业博览会将在粤开展

11月15日-18日&#xff0c;第十九届中国国际中小企业博览会&#xff08;简称“中博会”&#xff09;将在广州广交会展馆举办&#xff0c;共设8个展厅&#xff0c;展位总数约2800个&#xff0c;将举办超过30场系列配套活动&#xff0c;35个国家&#xff08;地区&#xff09;和国…...

云计算在智能交通系统中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 云计算在智能交通系统中的应用 云计算在智能交通系统中的应用 云计算在智能交通系统中的应用 引言 云计算概述 定义与原理 发展历…...

b4tman / docker-squid 可快速安装运行的、容器型代理服务器 + podman

使用容器部署&#xff0c;省时省力。 使用镜像&#xff0c;目前的最大麻烦就是之前各大镜像源纷纷关闭&#xff0c;需要自己找到合适的、安全的镜像源。 幸好 docker-squid 推广在 ghcr.io&#xff0c;目前下载没有障碍。 注&#xff1a;ghcr.io 是 GitHub Container Registry …...

脉冲神经网络(Spiking Neural Network,SNN)学习(1)

目录 一、神经网络 1、神经元 2、激活函数 &#xff08;1&#xff09;常见的激活函数&#xff1a;Sigmoid函数 &#xff08;2&#xff09;常见的激活函数&#xff1a;ReLU&#xff08;Rectified Linear Unit&#xff09;函数 &#xff08;3&#xff09;常见的激活函数&…...

【疑难杂症】电脑休眠后无法开机,进入 steamVR 时电脑突然黑屏关机

问题描述 1.电脑休眠后无法启动&#xff0c;只能拔电源再启动 2.进入 steamVR 时&#xff0c;电脑突然断电黑屏关机&#xff08;无蓝屏&#xff0c;无任何报错&#xff09; 3.在进行渲染时&#xff0c;如R23等&#xff0c;电脑突然黑屏关机 4.进入 VRChat 时&#xff0c;准备进…...

HTML文件中引入jQuery的库文件

方法一&#xff1a; 1. 首先&#xff0c;在官方网站(https://jquery.com/)上下载最新版本的jQuery库文件&#xff0c;通常是一个名为jquery-x.x.x.min.js的文件。 2. 将下载的jquery-x.x.x.min.js文件保存到你的项目目录中的一个合适的文件夹中&#xff0c;比如将它保存在你的项…...

IntelliJ IDEA超详细下载安装教程(附安装包)

目录 IDEA的简单介绍一、下载IDEA二、安装IDEA三、启动IDEA并使用1.配置IDEA2.输出&#xff1a;"Hello World&#xff01;" IDEA的简单介绍 IDEA 全称IntelliJ IDEA&#xff0c;是由 JetBrains 开发的一款广泛使用的集成开发环境&#xff08;IDE&#xff09;&#x…...

MySQL技巧之跨服务器数据查询:基础篇-更新语句如何写

MySQL技巧之跨服务器数据查询&#xff1a;基础篇-更新语句如何写 上一篇已经描述&#xff1a;借用微软的SQL Server ODBC 即可实现MySQL跨服务器间的数据查询。 而且还介绍了如何获得一个在MS SQL Server 可以连接指定实例的MySQL数据库的连接名: MY_ODBC_MYSQL 以及用同样的…...

期权懂|期权新手入门教学:期权合约有哪些要素?

期权小懂每日分享期权知识&#xff0c;帮助期权新手及时有效地掌握即市趋势与新资讯&#xff01; 期权新手入门教学&#xff1a;期权合约有哪些要素&#xff1f; 期权合约&#xff1a;是指约定买方有权在将来某一时间以特定价格买入或卖出约定标的物的标准化或非标准化合约。期…...

腾讯云nginx SSL证书配置

本章教程,记录在使用腾讯云域名nginx证书配置SSL配置过程。 一、nginx配置 域名和证书,替换成自己的即可。证书文件可以自定义路径位置。服务器安全组或者防火墙需要开放80和443端口。 server {#SSL 默认访问端口号为 443listen 443 ssl; #请填写绑定证书的域名server_name c…...

重新认识HTTPS

一. 什么是 HTTPS HTTP 由于是明文传输&#xff0c;所谓的明文&#xff0c;就是说客户端与服务端通信的信息都是肉眼可见的&#xff0c;随意使用一个抓包工具都可以截获通信的内容。 所以安全上存在以下三个风险&#xff1a; 窃听风险&#xff0c;比如通信链路上可以获取通信…...

应用于新能源汽车NCV4275CDT50RKG车规级LDO线性电压调节器芯片

关于车规级芯片&#xff08;Automotive Grade Chip&#xff09;&#xff0c;车规级芯片是专门用于汽车行业的芯片&#xff0c;具有高可靠性、高稳定性和低功耗等特点&#xff0c;以满足汽车电子系统的严格要求。这些芯片通常用于车载电子控制单元&#xff08;ECU&#xff09;和…...

GitLab 中文发行版最新版重点功能解读

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 学习极狐GitLab 的相关资料&#xff1a; 极狐GitLab 官网极狐…...