rust jni 简单试用
一般对于java jni 的开发可以直接使用c,c++,或者直接使用jna 以及jnr(直接使用java 代码就可以了,机制上还是三方库包装了一些公共的方便我们使用了),基于rust开发jni 也是一个不错的选择,比如zenoh 的java sdk (zenoh 基于rust,java sdk 使用了kotlin)
参考玩法
- 定义native 方法
package com.dalong;
public class MyAuthLib {
public native String getAuthToken(String username, String password);
}
- 生成头文件
此步骤在rust 以及c,c++ 原生开发中都是需要的,方便知道方法签名(当然直接手写也是可以的,对于rust 并不强需,核心是方法签名)
javac -h src/jni/myauth src/main/java/com/dalong/MyAuthLib.java
内容如下
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_dalong_MyAuthLib */
#ifndef _Included_com_dalong_MyAuthLib
#define _Included_com_dalong_MyAuthLib
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_dalong_MyAuthLib
* Method: getAuthToken
* Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_dalong_MyAuthLib_getAuthToken
(JNIEnv *, jobject, jstring, jstring);
#ifdef __cplusplus
}
#endif
#endif
- rust 开发项目
就是一个lib 项目cargo 信息
[package]
name = "myauthlib"
version = "0.1.0"
edition = "2024"
[lib]
crate-type = ["cdylib"]
[dependencies]
jni = "0.21.1"
[profile.release]
lto = "thin"
lib.rs
#[allow(non_snake_case)]
use jni::JNIEnv;
use jni::objects::{JObject, JString};
#[allow(unused_imports)]
use jni::sys::jstring;
#[unsafe(no_mangle)]
pub extern "system" fn Java_com_dalong_MyAuthLib_getAuthToken<'local>(
mut env: JNIEnv<'local>,
_ob: JObject<'local>,
name: JString<'local>,
password: JString<'local>,
) -> JString<'local> {
let name: String = env
.get_string(&name)
.expect("Couldn't get java string")
.into();
let password: String = env
.get_string(&password)
.expect("Couldn't get java string")
.into();
// Here you would implement your authentication logic
// For demonstration, we will just return a dummy token
let token = format!("{}:{}", name, password);
// Convert the Rust string to a Java string
let _ = env.new_string(token).expect("Couldn't create java string");
let java_str: JString = env
.new_string("hello")
.expect("Couldn't create java string");
java_str
}
- java 项目使用 核心是配置lib 地址(进行加载库)配置库加载位置(我为了方便将debug 的放到maven 项目中了)
public class App {
public static void main(String[] args) {
// Load the native library, 通过配置变量
System.loadLibrary("myauthlib");
// Create an instance of MyAuthLib
MyAuthLib myAuthLib = new MyAuthLib();
// Call the native method
while (true) {
try {
Thread.sleep(3000);
String authToken = myAuthLib.getAuthToken("user", "pass");
// Print the result
System.out.println("Authentication Token: " + authToken);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
说明
对于debug (比如我们使用了idea java 项目,同时使用了rust 插件)可以先启动java 项目(比如可能是web项目的,也可能是其他的,主要最好是long runing 的),然后将rust 的jni 项目附加到java 项目进程中,这样我们就可以进行debug了,如下图
通过rust 的jni 开发jni 扩展也是一个不错的选择,值得尝试下(至少相比c,c++的会简单方便不少)
参考资料
https://github.com/jni-rs/jni-rs
https://docs.rs/jni/latest/jni/
https://github.com/jnr/jnr-ffi