您的位置:首页 > 编程语言 > Java开发

JavaVM & JNIEnv

2016-10-13 15:24 405 查看
JNIEnv提供了大多数的JNI函数。你的本地方法都会接收JNIEnv作为第一个参数。
JNIEnv用于本地线程存储。因此,你不能在线程间共享同一个JNIEnv。
如果一个代码段没有其他方式获取它自身线程的JNIEnv,你可以共享JavaVM,用GetEnv来获取线程的JNIEnv。(假设这个线程有一个JavaVM;参见下面的AttachCurrentThread。)

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;
//    }
}


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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐