jni多线程问题
chenk818
2012-05-25
jni调用c++代码时,若c++实现里面采用了多线程,则会出现jvm crash的情况,查了一下jni的说明,其中提到:JNIEnv *env指针不可为多个线程共用。但这个说的是env无法在java的各个线程中共用,我遇到的情况是java只有一个线程,而c++实现有多线程,求教。。。
|
|
RednaxelaFX
2012-05-25
首先确认一下你确实读到了官方文档: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环境里了。 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。所以你会在各种例子里面看到人家这样写: JavaVM* jvm = NULL; JNIEnv* env = NULL; void* vm_args = ...; jint res = JNI_CreateJavaVM(&jvm, &env, vm_args); if (res < 0) { // Create JVM failed ... } 这样调用完之后env就指向了一个可用的JNIEnv。 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。 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。 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线程是自己加载一个?还是多个线程公用同一个?
这种模糊的描述很容易有误差…不过通常这种问题的答案都是“全局变量只有一份,多线程间共用”。 |