一文解秘Rust如何与Java互操作

在这里插入图片描述

本博客所有文章除特别声明外,均采用CC BY-NC-SA 4.0许可协议。转载请注明来自 唯你

使用场景

JAVA 与 Rust 互操作让 Rust 可以背靠 Java 大生态来做更多事情,而 Java 也可以享受 Rust 语言特性的内存安全,所有权机制,无畏并发。

互操作的典型场景包括:

  • 性能优化:利用 Rust 处理计算密集型任务,提高 Java 应用的整体性能。
  • 系统级编程:结合 Rust 的底层控制能力与 Java 的高级抽象,实现更高效的系统交互。
  • 跨平台开发:使用 Rust 编写核心逻辑,通过 JNI 在不同平台上与 Java 交互,实现高效跨平台开发。
  • 安全关键应用:在金融、医疗等领域,利用 Rust 处理敏感数据和核心功能,保证高度安全性。
  • 实时系统:在游戏引擎、音频处理等延迟敏感的应用中,使用 Rust 处理时间关键部分。

背景知识

JNI

image.png

  • 全称 Java Native Interface,它允许 Java 代码与其他语言(如 C 或 C++)编写的应用程序进行互操作。
  • JNI Specification:这是 JNI 的官方规范,详细描述了 JNI 的使用方法、接口和功能。

Java 虚拟机(JVM)

image 1.png

JNI 是 Java 虚拟机的一部分,JVM 在启动时为每个线程创建一个 JNI 环境。JNI 环境包括指向 JVM 内部数据结构的指针,这些数据结构用于存储 Java 对象、方法和字段的信息。

JNIEnv (JNI 环境)

image 2.png

  • JNIEnv是一个指向结构体的指针,代表当前线程的 JNI 环境。它包含所有 JNI 相关函数的指针,让你能在本地代码中使用这些函数。每个线程都有自己独立的JNIEnv,所以不能在不同线程间传递这个指针。
  • 可以将JNIEnv视为一个"翻译器"。当 Rust 代码需要与 Java 交互时,它通过这个"翻译器"发送请求,当调用 Java 方法或获取 Java 对象的属性。每个线程都拥有自己独立的"翻译器",这确保了各线程与 Java 交互时的独立性。

另外

  • 当 Java 代码调用本地方法时,JVM 会加载相应的本地库并创建一个JNIEnv指针。
  • 本地代码可以使用这个指针访问 JNI 提供的函数,进行 Java 对象的操作。
  • 每个线程有独立JNIEnv,保证线程安全。新线程需调用AttachCurrentThread获取对应JNIEnv
  • JNI 提供了数据类型转换机制,实现 Java 与 C/C++之间的数据传递。

在 Rust 生态中使用 jni 0.21.1 库可以实现与 Java 代码的交互。

JNI 0.21.1 简介

该项目为 Rust 提供了完整的 JNI 绑定,允许:

  • 使用 Rust 代码与 Java 库进行交互,调用 Java 方法和访问 Java 对象。

  • 从 Rust 代码中使用 Java 类和接口。

  • 实现跨语言的高效数据交换。

  • 利用 Rust 的性能优势和 Java 的成熟生态系统

跨平台 UI 框架 Flutter 源码中的 MethodChannel 实现了 Dart 与 Android 层的通信,其底层 C++也是通过 JNI 调用插件中的 onMethodCall 来实现的。这与上述 jni 0.21.1 采用了相同的思路,但存在以下不同点:

  • 语言特性和类型安全:
    Rust 的jni库提供了一种更安全的方式来处理 Java 对象和方法调用。它利用 Rust 的所有权系统来减少潜在的内存错误,使得在 Rust 中使用 JNI 时更易于管理资源和避免常见错误。
  • 多平台支持:jni 0.21.1 提供了更广泛的跨平台支持。

如何运行示例

示例源码请阅读原文,见原文底部源码获取

在 Windows 11 环境下运行示例时,笔者遇到了两个问题:

  1. Windows 自带的 PowerShell 无法直接执行 Makefile
  2. 由于 Rust 配置了特定目标平台,出现了不明原因的编译错误

以下是解决这些问题的方法:

在 MinGW-w64 中执行 Makefile

  1. 确保已在 MinGW-w64 环境中安装 mingw32-make 工具(通常随 MinGW-w64 一起安装)
  2. 打开 MinGW-w64 命令行
  3. 导航至 Makefile 所在目录
  4. 执行以下命令
//当前示例中是makefile,直接执行mingw32-make -f makefile即可
mingw32-make -f YourMakefileName

确认当前 Rust 环境

举例来说,笔者在 C:\Users\xxx.cargo 目录下配置了 config.toml 文件:

[build]
target = "aarch64-linux-android"

这导致在 Windows 上使用 mingw32-make 来编译针对 Android 平台的 Rust .so 文件,造成了混乱并引发了莫名其妙的编译错误。解决方法是删除不必要的 config.toml 文件,确保当前运行环境与目标平台(如 Windows)一致。

输出结果:

Hello, josh!
[B@2f92e0f4
factCallback: res = 720
counterCallback: count = 1
counterCallback: count = 2
counterCallback: count = 3
counterCallback: count = 4
counterCallback: count = 5
Invoking asyncComputation (thread id = 1)
asyncCallback: thread id = 23, progress = 0%
asyncCallback: thread id = 23, progress = 10%
asyncCallback: thread id = 23, progress = 20%
asyncCallback: thread id = 23, progress = 30%
asyncCallback: thread id = 23, progress = 40%
asyncCallback: thread id = 23, progress = 50%
asyncCallback: thread id = 23, progress = 60%
asyncCallback: thread id = 23, progress = 70%
asyncCallback: thread id = 23, progress = 80%
asyncCallback: thread id = 23, progress = 90%
asyncCallback: thread id = 23, progress = 100%

示例简析

让我们深入分析示例中 asyncComputation 的流程。其核心目的是在 Rust 端执行一个异步计算,同时 Rust 端会调用 Java 端来报告计算进度。

image.png

整体流程图说明:

  1. Java 的 main()方法调用 asyncComputation()。
  2. asyncComputation()通过 JNI 调用 Rust 的 Java_HelloWorld_asyncComputation()函数。
  3. Rust 函数创建一个新线程来执行异步计算。
  4. 在新线程中,Rust 执行计算并周期性地调用 Java 的 asyncCallback()方法报告进度。
  5. 当 Rust 完成计算后,控制权返回到 Java 的主线程。

这个过程展示了 Java 调用 Rust(步骤 1)和 Rust 回调 Java(步骤 4)的双向交互。

源码如下

image 3.png

#1 将一个 HelloWorld 类实例传递给 Rust 端,这对应下方 Rust 侧实现中 #3 处的 callback 对象

image 4.png

Rust 实现说明

  1. JNIEnv 参数:详见上述相关概念中的解释。
  2. JClass:代表调用此本地方法的 Java 类引用,主要用于访问类级别的静态方法和字段。
  3. callback:Java 中新创建的 HelloWorld 对象实例。
  4. 获取 JVM 对象:因为 env 对象不支持线程间传递和共享(仅实现了 Send),而 JVM 支持。通过 JVM 对象可在线程间传递,并最终获得 env
  5. 创建全局引用:获取 HelloWorld() 实例对象的全局引用,防止被垃圾回收。
  6. 线程安全:每个线程都有自己的 JNIEnv,确保线程安全。在新线程中需调用 AttachCurrentThread 获取对应的 JNIEnv
  7. 反向调用 Java:通过 env 反向调用 Java 代码。调用对象是新创建的 HelloWorld 实例,回调方法是其中的 asyncCallback。在 JNI 中,"(I)V" 是方法签名,描述了 Java 方法的参数和返回类型。"(I)V" 表示接受一个整数参数并返回 void 的方法。在这里,asyncCallback 方法接收一个整数(progress)作为参数,无返回值。

总结

  1. Java 与 Rust 互操作让两种语言优势互补,提高性能和安全性,适用于多种场景如性能优化、系统级编程和跨平台开发。
  2. JNI(Java Native Interface)是实现 Java 与 Rust 互操作的关键技术,允许 Java 代码与其他语言编写的应用程序进行交互。
  3. 通过示例分析,我们了解了 Java 调用 Rust 函数和 Rust 回调 Java 方法的双向交互过程,展示了两种语言之间的无缝协作。

参考链接

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

JNI APIs and Developer Guides

Leveraging Rust in our high-performance Java database

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/467277.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

信息安全工程师(82)操作系统安全概述

一、操作系统安全的概念 操作系统安全是指操作系统在基本功能的基础上增加了安全机制与措施,从而满足安全策略要求,具有相应的安全功能,并符合特定的安全标准。在一定约束条件下,操作系统安全能够抵御常见的网络安全威胁&#xff…

微服务系列四:热更新措施与配置共享

目录 前言 一、基于Nacos的管理中心整体方案 二、配置共享动态维护 2.1 分析哪些配置可拆,需要动态提供哪些参数 2.2 在nacos 分别创建共享配置 创建jdbc相关配置文件 创建日志相关配置文件 创建接口文档配置文件 2.3 拉取本地合并配置文件 2.3.1 拉取出现…

线程级耗时统计工具类TimeWatcher

线程级耗时统计工具类TimeWatcher 先看效果 假设我们的业务代码逻辑是这样的 那么最终的日志打印效果为(注:此为美化输出,也可设置为常规一行输出,还可自定义) 2024-11-08T23:48:53.39008:00 INFO 31472 --- [nio-…

arkUI:Flex弹性布局的各个属性

arkUI:Flex弹性布局的简单使用 1 主要内容说明2 相关内容2.1 Flex弹性布局的方向2.1.1 源码1的简答说明2.1.2 源码1 (Flex弹性布局的方向)2.1.3 源码1运行效果2.1.3.1 当direction: FlexDirection.RowReverse2.1.3.2 当direction: FlexDirect…

详解Gemini API的使用:在国内实现大模型对话与目标检测教程

摘要:本博客介绍了如何利用Gemini API实现多轮对话和图像目标检测识别功能,在Python中快速搭建自己的大模型完成实际任务。通过详细的步骤解析,介绍了如何申请Gemini API密钥,调用API、对话实现的代码,给出了上传图片识…

5G时代已来:我们该如何迎接超高速网络?

内容概要 随着5G技术的普及,我们的生活似乎变得更加“科幻”了。想象一下,未来的智能家居将不仅仅是能够听你说“开灯”;它们可能会主动询问你今天心情如何,甚至会推荐你一杯“维他命C芒果榨汁”,帮助你抵御夏天的炎热…

算法每日练 -- 双指针篇(持续更新中)

介绍: 常见的双指针有两种形式,一种是对撞指针(左右指针),一种是快慢指针(前后指针)。需要注意这里的双指针不是 int* 之类的类型指针,而是使用数组下标模拟地址来进行遍历的方式。 …

理解鸿蒙app 开发中的 context

是什么 Context是应用中对象的上下文,其提供了应用的一些基础信息,例如resourceManager(资源管理)、applicationInfo(当前应用信息)、dir(应用文件路径)、area(文件分区…

贝尔不等式,路径积分与AB(Aharonov-Bohm)效应

贝尔不等式、路径积分与Aharonov-Bohm(AB)效应 这些概念分别源于量子力学不同的理论分支和思想实验,但它们都揭示了量子力学的奇异性质,包括非局域性、相位效应和波粒二象性。以下详细解析每一概念,并探讨其相互联系。…

python 爬虫 入门 六、Selenium

Selenium本来是一个自动测试工具,用于模拟用户对网站进行操作。在爬虫领域也有其用处。 一、下载安装Selenium及附属插件 pip install Selenium 安装完成后还需要安装一个浏览器驱动,来让python能启动浏览器。 如果是Edge或者其他基于Chromium的浏览器…

Linux(CentOS)yum update -y 事故

CentOS版本:CentOS 7 事情经过: 1、安装好CentOS 7,系统自带JDK8,版本为:1.8.0_181 2、安装好JDK17,版本为:17.0.13 3、为了安装MySQL执行了 yum update -y(这个时候不知道该命令的…

uniapp uni-calendar日历实现考勤统计功能

根据日历组件代码结构 构成相应结构的状态统计数据 list 再遍历到每日的子组件中 <view class"uni-calendar__weeks-item" v-for"(weeks,weeksIndex) in item" :key"weeksIndex"><calendar-item class"uni-calendar-item--hook&q…

环境配置与搭建

安装pytorch 官网连链接&#xff1a;https://pytorch.org/ 特殊包名 cv2 pip install opencv-python sklearn pip install scikit-learnPIL pip install Pillow使用jupyter notebook pip install jupyter安装显卡驱动 Windows Linux 视频教程&#xff1a; 【ubuntu2…

【数据库实验一】数据库及数据库中表的建立实验

目录 实验1 学习RDBMS的使用和创建数据库 一、 实验目的 二、实验内容 三、实验环境 四、实验前准备 五、实验步骤 六、实验结果 七、评价分析及心得体会 实验2 定义表和数据库完整性 一、 实验目的 二、实验内容 三、实验环境 四、实验前准备 五、实验步骤 六…

SpringBoot健身房管理:技术与实践

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

CulturalBench :一个旨在评估大型语言模型在全球不同文化背景下知识掌握情况的基准测试数据集

2024-10-04&#xff0c;为了提升大型语言模型在不同文化背景下的实用性&#xff0c;华盛顿大学、艾伦人工智能研究所等机构联合创建了CulturalBench。这个数据集包含1,227个由人类编写和验证的问题&#xff0c;覆盖了包括被边缘化地区在内的45个全球区域。CulturalBench的推出&…

python登录功能实现

一.用python实现基本的登录功能 #-----------------1.基本登录功能------------------- nameinput("qq账号&#xff1a;") if name"jc":passwdinput("密码&#xff1a;")if passwd"123456":print("登录成功")else:print(&q…

如何使用Python管理环境变量

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 环境变量 📒📝 环境变量简介📝 Python 中的环境变量操作📝 获取环境变量📝 设置环境变量🔖 临时设置🔖 永久设置📝 删除环境变量📝 临时删除📝 永久删除📝 小结⚓️ 相关链接 ⚓️📖 介绍 📖 环境变量…

设置允许多用户远程登录 Windows 云服务器

操作场景 本文档以 Windows Server 2016 操作系统云服务器为例&#xff0c;指导您配置多用户远程登录 Windows 云服务器。 注意&#xff1a; 微软提供的多用户远程登录功能试用期为120天&#xff0c;若未购买多用户登录授权&#xff08;RDS CALs&#xff09;&#xff0c;则试…

喜报!景联文科技成功通过DCMM数据管理能力成熟度二级认证

10月30日&#xff0c;中国电子信息行业联合会公示了新一批DCMM贯标企业&#xff0c;景联文科技成功通过DCMM数据管理能力成熟度二级认证&#xff08;乙方认证&#xff09;。 DCMM是《数据管理能力成熟度评估模型》的简称&#xff0c;是我国在数据管理领域首个正式发布的国家标准…