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

JNI跨线程使用JNIEnv报错:调用FindClass触发检测错误原因咨询

错误原因分析:JNI跨线程使用JNIEnv导致的JNI DETECTED ERROR

错误核心原因

错误日志明确指出:

java_vm_ext.cc:579] JNI DETECTED ERROR IN APPLICATION: thread Thread[21,tid=15479,Native,Thread*=0x7d932413a0,peer=0x12f00038,"ImageReader-640x480f23u3m2-15444-0"] using JNIEnv* from thread Thread[1,tid=15444,Runnable,Thread*=0x7d931f4be0,peer=0x71d8ae98,"main"]

JNIEnv是线程绑定的资源,每个线程只能使用自己专属的JNIEnv实例,绝对不能跨线程直接复用其他线程的JNIEnv指针。

代码问题分析

  • 在callJavaFun函数中,你传入的jniEnv是来自主线程(Thread[1])的实例,但这个函数实际是在ImageReader对应的Native线程(Thread[21])中执行的,跨线程使用JNIEnv触发了虚拟机的错误检测。
  • 而Java_com_test_testQ_Yolov8Ncnn_test是标准的JNI入口函数,它的env参数是当前调用线程(主线程)的专属JNIEnv,所以执行不会有异常。

正确处理方式(补充)

如果需要在非JNI入口的线程中调用Java方法,应该通过全局保存的JavaVM实例获取当前线程的JNIEnv:

void callJavaFun(
        JNIEnv *jniEnv,
        jobject thiz,
        JavaVM *jniGvm,
        jmethodID methodID,
        jclass globalClass,
        cv::Mat &rgb
) {
    JNIEnv *currentEnv = nullptr;
    // 附加当前线程到JVM并获取专属JNIEnv
    jint result = jniGvm->AttachCurrentThread(&currentEnv, nullptr);
    if (result == JNI_OK) {
        jclass clazz = currentEnv->FindClass("com/test/testQ/Yolov8Ncnn");
        jmethodID methodID = currentEnv->GetMethodID(clazz, "test", "()V");
        if (methodID != NULL) {
            currentEnv->CallVoidMethod(thiz, methodID);
        }
        // 如果是临时创建的Native线程,需要执行detach;JVM管理的线程无需此操作
        jniGvm->DetachCurrentThread();
    }
}

内容的提问来源于stack exchange,提问作者Mustafa Maden

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 19:01:06