本机方法中的致命错误:在非 Java 线程中使用 JNIEnv

Qix*_*Qix 2 java java-native-interface

我正在实现一些 JNI 回调(本机 -> java)功能以及另一个更大的本机框架,并且在该框架的一个回调上我在尝试回调到java时收到此错误。

FATAL Error in native method: Using JNIEnv in non-java thread
Run Code Online (Sandbox Code Playgroud)

这到底是什么意思?什么是 java 线程,如何在另一个本机线程中使用 JNI?

Qix*_*Qix 7

Java必须附加到要在其上执行的线程。

JNI 接口指针 ( JNIEnv) 仅在当前线程中有效。如果另一个线程需要访问 Java VM,它必须首先调用 AttachCurrentThread() 将自己附加到 VM 并获取 JNI 接口指针。一旦附加到 VM,本机线程就像运行在本机方法中的普通 Java 线程一样工作。

为此,您必须存储一个指向 JVM 对象的指针,通过JNI_OnLoad()导出或通过native使用(JNIEnv*)java->GetJavaVm(&(JavaVM*)jvm);.

从那里,每次您需要使用 JNI 时,只需调用以下代码即可附加到当前线程并检索新JNIEnv*指针。

JNIEnv* AttachJava()
{
    JavaVMAttachArgs args = {JNI_VERSION_1_2, 0, 0};
    JNIEnv* java;
    jvm->AttachCurrentThread((void**) &java, &args);
    return java;
}
Run Code Online (Sandbox Code Playgroud)

不要保存 的实例,JNIEnv*除非您确定它们将在同一线程中被引用。

正如文档所述,调用AttachCurrentThread已经附加的线程是无操作的,因此是无害的。