我已经知道每次使用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);
}
如您所见,我将线程附加两次,因为没有第二个,代码崩溃了。但如果它们像互斥体一样,只需要第一个。你能帮助我吗,为什么我每次都需要它们?是否像代码一样保存?
答案 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()
被多个线程调用,则必须使用真正的互斥锁。
通常,在与虚拟机交互时,您需要附加一次线程并将其保持较长时间,而不是在每个方法之后将其分离。