You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过JNI从同步Java函数调用Rust异步函数?

基于Rust JNI实现Java侧调用Rust异步函数的方案

你要的核心是在Rust侧的同步JNI导出函数内执行异步逻辑,直接借助Rust异步运行时的阻塞等待接口即可实现,具体实现步骤如下:

1 Rust侧核心实现

依赖配置

先在Cargo.toml中引入必要依赖:

[package]
name = "evo"
version = "0.1.0"
edition = "2021"

[dependencies]
jni = "0.21"
tokio = { version = "1.0", features = ["rt-multi-thread", "macros"] }
once_cell = "1.18"

代码实现

用全局共享的异步运行时避免重复创建开销,同步JNI函数内调用block_on执行异步任务:

use jni::objects::{JClass, JObject};
use jni::sys::jobject;
use jni::JNIEnv;
use once_cell::sync::Lazy;
use tokio::runtime::Runtime;

// 全局异步运行时实例
static RUNTIME: Lazy<Runtime> = Lazy::new(|| {
    tokio::runtime::Builder::new_multi_thread()
        .enable_all()
        .build()
        .unwrap()
});

// 你的异步业务函数
async fn async_create_main_worker() -> MainWorker {
    // 这里放异步逻辑
    MainWorker {}
}

// JNI导出的同步函数,对应Kotlin侧的create_main_worker外部方法
#[no_mangle]
pub extern "system" fn Java_quest_evo_runtime_Library_create_1main_1worker(
    env: JNIEnv,
    _class: JClass,
) -> jobject {
    // 阻塞等待异步任务执行完成
    let worker = RUNTIME.block_on(async_create_main_worker());
    // 把Rust侧结构体转换成Java侧的MainWorker对象返回,这里按你的实际对象映射逻辑实现
    let java_worker = env.new_object("quest/evo/runtime/objects/MainWorker", "()V", &[]).unwrap();
    java_worker.into_raw()
}

// 示例用的Rust侧MainWorker结构体
struct MainWorker {}

2 Kotlin侧加载逻辑

你提供的本地库加载代码可以直接使用,格式化后如下:

package quest.evo.runtime

import quest.evo.runtime.objects.MainWorker
import java.io.File
import java.io.FileOutputStream

object Library {
    external fun create_main_worker(): MainWorker;

    init {
        val tempDir = File(System.getProperty("java.io.tmpdir"))
        try {
            if (tempDir.exists()) {
                val os = System.getProperty("os.name")
                val extension = if (os.startsWith("Windows")) ".dll" else if (os.startsWith("Mac OS")) ".dylib" else ".so"
                if (tempDir.canWrite()) {
                    val file = File(tempDir, "libevo$extension")
                    file.delete()
                    file.createNewFile()
                    try {
                        Library::class.java.classLoader.getResourceAsStream("libevo$extension").use { inputStream ->
                            FileOutputStream(file.absolutePath).use { outputStream ->
                                val buffer = ByteArray(4096)
                                if (inputStream != null) {
                                    while (true) {
                                        val length = inputStream.read(buffer)
                                        if (length == -1) {
                                            break
                                        }
                                        outputStream.write(buffer, 0, length)
                                    }
                                }
                            }
                        }
                    } catch (ignored: Exception) {
                    }
                    System.load(file.absolutePath)
                } else {
                    println("Cannot write to the temp directory.")
                }
            } else {
                println("Cannot find the temp directory.")
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    @JvmStatic
    fun main(args: Array<String>) {
        val test = create_main_worker();
    }
}

注意事项

  • 如果不需要同步等待结果,可在Rust侧将异步任务提交到运行时后立刻返回任务标识,后续通过回调或者轮询接口获取结果,避免阻塞Java调用线程
  • 长耗时异步任务不要在Java主线程调用,避免界面卡顿或者ANR问题
  • JNI函数名要严格遵循命名规范,方法名中的下划线需要转义为_1,和示例中的create_1main_1worker一致

内容的提问来源于stack exchange,提问作者Carter Davis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 18:09:02