JNIEnv提供了大多数的JNI函数。你的本地方法都会接收JNIEnv作为第一个参数。
JNIEnv用于本地线程存储。因此,你不能在线程间共享同一个JNIEnv。
如果一个代码段没有其他方式获取它自身线程的JNIEnv,你可以共享JavaVM,用GetEnv来获取线程的JNIEnv。(假设这个线程有一个JavaVM;参见下面的AttachCurrentThread。)
![复制代码](https://common.cnblogs.com/images/copycode.gif)
static JavaVM *myVm;
/* * This is called by the VM when the shared library is first loaded. */ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) { myVm = vm; jint result = -1; JNIEnv* env = NULL; LOGI("JNI_OnLoad"); if (vm->GetEnv((void **)&env, JNI_VERSION_1_4) != JNI_OK) { LOGE("ERROR: GetEnv failed"); goto bail; } // initClassHelper(env, "com/example/camera/AnObject", &gCameraViewObject); if (registerNatives(env) != JNI_TRUE) { LOGE("ERROR: registerNatives failed"); goto bail; } result = JNI_VERSION_1_4; bail: return result; } void JNI_OnUnload(JavaVM* vm, void* reserved) { // JNIEnv* env = NULL; LOGI("JNI_OnUnload"); // if (vm->GetEnv((void **)&env, JNI_VERSION_1_4) != JNI_OK) { // LOGE("ERROR: GetEnv failed"); // return; // } // // if (gCameraViewObject != NULL) { // env->DeleteGlobalRef(gCameraViewObject); // gCameraViewObject = NULL; // } }
![复制代码](https://common.cnblogs.com/images/copycode.gif)
![复制代码](https://common.cnblogs.com/images/copycode.gif)
JNIEnv* Android_JNI_GetEnv(void) { /* From http://developer.android.com/guide/practices/jni.html * All threads are Linux threads, scheduled by the kernel. * They're usually started from managed code (using Thread.start), but they can also be created elsewhere and then * attached to the JavaVM. For example, a thread started with pthread_create can be attached with the * JNI AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a thread is attached, it has no JNIEnv, * and cannot make JNI calls. * Attaching a natively-created thread causes a java.lang.Thread object to be constructed and added to the "main" * ThreadGroup, making it visible to the debugger. Calling AttachCurrentThread on an already-attached thread * is a no-op. * Note: You can call this function any number of times for the same thread, there's no harm in it */ JNIEnv *env; int status = (*myVm)->AttachCurrentThread(myVm, &env, NULL); if(status < 0) { LOGE("failed to attach current thread"); return 0; } /* From http://developer.android.com/guide/practices/jni.html * Threads attached through JNI must call DetachCurrentThread before they exit. If coding this directly is awkward, * in Android 2.0 (Eclair) and higher you can use pthread_key_create to define a destructor function that will be * called before the thread exits, and call DetachCurrentThread from there. (Use that key with pthread_setspecific * to store the JNIEnv in thread-local-storage; that way it'll be passed into your destructor as the argument.) * Note: The destructor is not called unless the stored value is != NULL * Note: You can call this function any number of times for the same thread, there's no harm in it * (except for some lost CPU cycles) */ pthread_setspecific(mThreadKey, (void*) env); return env; }标签:thread,JavaVM,void,env,JNI,JNIEnv From: https://www.cnblogs.com/kn-zheng/p/17004984.html