心胸决定格局,眼界决定境界...

jni多线程问题

AttachCurrentThreadAsDaemon(JavaVM* vm, void** penv, void* args);  

 

首先确认一下你确实读到了官方文档:http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/jniTOC.html 

JNIEnv不能在任意线程中使用。必须是原本就是Java线程(Java代码通过JNI调用native代码时,发起调用的那个肯定是Java线程),或者是让已有的native线程通过JNI来attach到Java环境。 
你的每个“C++线程”里都应该要调用AttachCurrentThread()来确保它确实attach到Java环境里了。 

C代码  收藏代码
  1. jint JNI_CreateJavaVM(JavaVM **p_vm, JNIEnv **p_env, void *vm_args);  

http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/invocation.html#wp16334 
这个函数会通过p_env来返回适合这个通过JNI创建JVM实例的线程使用的JNIEnv。所以你会在各种例子里面看到人家这样写: 
C代码  收藏代码
  1. JavaVM* jvm = NULL;  
  2. JNIEnv* env = NULL;  
  3. void* vm_args = ...;  
  4. jint res = JNI_CreateJavaVM(&jvm, &env, vm_args);  
  5. if (res < 0) {  
  6.   // Create JVM failed ...  
  7. }  

这样调用完之后env就指向了一个可用的JNIEnv。 

C代码  收藏代码
  1. jint AttachCurrentThread(JavaVM *vm, JNIEnv **p_env, void *thr_args);  

http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/invocation.html#attach_current_thread
同样通过p_env来返回。这是把当前线程(一个已有的native线程)attach到Java环境里。同一个线程反复调用attach不会真的反复attach。 

C代码  收藏代码
  1. jint AttachCurrentThreadAsDaemon(JavaVM* vm, void** penv, void* args);  

http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/invocation.html#attach_current_thread_as_daemon
同上。只是attach的时候指定作为daemon线程来attach。 

C代码  收藏代码
  1. jint GetEnv(JavaVM *vm, void **env, jint version);  

http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/invocation.html#GetEnv 
通过JavaVM获取当前线程适用的JNIEnv,通过env返回。如果当前线程没有attach到Java环境里,那么env会被置为NULL,而GetEnv的返回值会是JNI_EDETACHED。
 
ytulgr 2013-01-16
JAVA多个线程调用C++ Native库方法,C++ Native库中有一个全局变量,多个Java线程是自己加载一个?还是多个线程公用同一个?
 
RednaxelaFX 2013-01-16
ytulgr 写道
JAVA多个线程调用C++ Native库方法,C++ Native库中有一个全局变量,多个Java线程是自己加载一个?还是多个线程公用同一个?

这种模糊的描述很容易有误差…不过通常这种问题的答案都是“全局变量只有一份,多线程间共用”。

 

http://hllvm.group.iteye.com/group/topic/33519

posted @ 2016-03-04 15:10  WELEN  阅读(1751)  评论(0)    收藏  举报