当我尝试调用java类中的函数时,出现以下错误。
ava_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"]
java_vm_ext.cc:579] in call to FindClass.
代码;
void callJavaFun(
JNIEnv *jniEnv,
jobject thiz,
JavaVM *jniGvm,
jmethodID methodID,
jclass globalClass,
cv::Mat &rgb
) {
jclass clazz = jniEnv->FindClass("com/test/testQ/Yolov8Ncnn");
jmethodID methodID = jniEnv->GetMethodID(clazz, "test", "()V");
if (methodID != NULL) {
jniEnv->CallVoidMethod(thiz, methodID);
}
}
当我运行以下代码行中的代码时,我没有任何问题。
JNIEXPORT jboolean JNICALL
Java_com_test_testQ_Yolov8Ncnn_test(JNIEnv *env, jobject thiz, jobject surface) {
...
return JNI_TRUE;
}
原因是什么?
您遇到的错误通常发生在您尝试在另一个线程中使用从一个线程获取的 JNIEnv 指针时。 JNIEnv 特定于获取它的线程,不应在不同的线程中使用。
在“callJavaFun”函数中,您将 jniEnv 参数(可能是在另一个线程中获得的)传递给 jniEnv->FindClass(“com/test/testQ/Yolov8Ncnn”),然后尝试使用它来查找类并在不同的线程中调用方法。这在 JNI 中是不允许的。
如果需要从另一个线程调用 JNI 函数,则应该使用 AttachCurrentThread 和 DetachCurrentThread 等 JavaVM 函数获取专门针对该线程的新 JNIEnv 指针。 AttachCurrentThread用于获取当前线程的JNIEnv指针,执行JNI操作,然后DetachCurrentThread用于在完成后释放JNIEnv。这可确保您以线程安全的方式使用 JNIEnv。以下是如何修改代码以在另一个线程中正确调用 JNI 函数的示例:
void callJavaFun(
JNIEnv *jniEnv,
jobject thiz,
JavaVM *jniGvm,
jmethodID methodID,
jclass globalClass,
cv::Mat &rgb
) {
JNIEnv *threadEnv = nullptr;
if (jniGvm->AttachCurrentThread(&threadEnv, NULL) == JNI_OK) {
jclass clazz = threadEnv->FindClass("com/test/testQ/Yolov8Ncnn");
jmethodID methodID = threadEnv->GetMethodID(clazz, "test", "()V");
if (methodID != NULL) {
threadEnv->CallVoidMethod(thiz, methodID);
}
jniGvm->DetachCurrentThread();
}
}