JavaVM接口
第一種方式,在加載動態鏈接庫的時候,JVM會調用JNI_OnLoad(JavaVM* jvm, void* reserved)(如果定義了該函數)。第一個參數會傳入JavaVM指針。一般都在這個時候保存一個static的JavaVM *jvm,這個jvm指針在進程內是可以放心共享的。
第二種方式,在native code中調用JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args)可以得到JavaVM指針。
兩種情況下,都可以用全局變量,比如JavaVM* g_jvm來保存獲得的指針以便在任意上下文中使用。
Android系統是利用第二種方式Invocation interface來創建JVM的。
JNIEnv接口
JNI開發最常見的錯誤就是濫用了JNIEnv接口。需要強調的是JNIEnv是跟線程相關的。sdk文檔中強調了do not cache JNIEnv*,要用的時候在不同線程中再通過JavaVM *jvm的方法來獲取與當前線程相關的JNIEnv*。
在native method中,JNIEnv作爲第一個參數傳入。那麼在JNIEnv不作爲參數傳入的時候,該如何獲得它?JNI提供了兩個函數:(*jvm)->AttachCurrentThread(jvm, (void**)&env, NULL)和(*jvm)->GetEnv(jvm, (void**)&env, JNI_VERSION_1_2)。兩個函數都利用JavaVM接口獲得JNIEnv接口,上面已經講到如何獲得JavaVM接口。當創建的線程需要獲取JNIEnv*的時候,最好在剛創建的時候調用一次AttachCurrentThread,最好還是不要緩存這個JNIEnv*,每次需要的時候通過JavaVM*獲取,不要忘記線程結束的時候執行DettachCurrentThread。
JNI規範也說明,可以將獲得JNIEnv封裝成一個函數。
1 |
JNIEnv*
JNU_GetEnv() |
2 |
{ |
3 |
JNIEnv*
env; |
4 |
(*g_jvm)->GetEnv(g_jvm,
( void **)&env,
JNI_VERSION_1_2); |
5 |
return env; |
6 |
} |
轉貼:http://blog.csdn.net/lirunfa/article/details/8030094