多线程JNI调用

时间:2014-10-21 11:31:53

标签: java c++ c multithreading java-native-interface

我已经知道每次使用jvm->AttachCurrentThread时我都必须使用JNIEnv将c-threads附加到jvm。这应该与互斥锁非常相似,我在方法的开头用jvm->AttachCurrentThread锁定它,并在最后用jvm->DetachCurrentThread()解锁它。 所以,现在我有一个方法,我使用JNIEnv moreoften。我每次都必须致电AttachCurrentThread吗?这里有一个代码示例:

  std::unique_ptr<IState> JNIGame::createEmptyState() {
    JNIEnv* env;
    jvm->AttachCurrentThread((void**)&env, NULL);
    if(!jGame_createEmptyState)
      jGame_createEmptyState =  env->GetMethodID(jGameC, "createEmptyState", "()Ljni/JNIGames$IJNIState;");

    JNIState *state = new JNIState();
    //needed?
    jvm->AttachCurrentThread((void**)&env, NULL);
    state->jStateO = env->CallObjectMethod(jGameO, jGame_createEmptyState);
    jvm->DetachCurrentThread();
    return std::unique_ptr<IState>(state);
}

如您所见,我将线程附加两次,因为没有第二个,代码崩溃了。但如果它们像互斥体一样,只需要第一个。你能帮助我吗,为什么我每次都需要它们?是否像代码一样保存?

2 个答案:

答案 0 :(得分:0)

不确定你的意思&#34;表现得像互斥锁,&#34;但文档说,&#34;尝试附加已经附加的线程是无操作。&#34;

您的示例附加两次,然后分离一次。第二次附着没有效果。

我引用的那句话来自&#34; Invocation API&#34; JNI文档的一章。 &#34;调用API&#34;他们称之为从C调用Java所需的收集方法(而不是用于编写可以从 Java调用的本机方法的方法。)


值得一提的几点:

启动JVM的线程是隐式附加的。该线程成为JVM&#34; main&#34;线程。

每当最后一个非守护程序线程退出时,JVM将关闭(无法重新启动)。如果本机线程分离,则将其视为线程退出。

我的应用程序有专门的&#34;主要&#34;启动JVM的线程,通知其他线程它已启动,然后永远休眠。睡觉&#34;主要&#34;当我的应用程序的其他本机线程都没有使用它时,线程就是让我的JVM保持活动状态。

答案 1 :(得分:0)

AttachCurrentThread允许添加您在JVM外部创建的线程以添加到Java虚拟机。它并不打算“每次使用JNIEnv”时都称为“并非”类似于互斥体“。

此外,引用the documentation

  

尝试附加已经附加的线程是无操作。

如果您的代码崩溃,可能是因为AttachCurrentThread 是互斥锁。如果您的方法JNIGame::createEmptyState()被多个线程调用,则必须使用真正的互斥锁。

通常,在与虚拟机交互时,您需要附加一次线程并将其保持较长时间,而不是在每个方法之后将其分离。