局部引用問題
1.一個局部引用僅在創建它的native函數及該函數調用的函數中有效。在一個native函數執行期間創建的所有局部引用將在該函數返回時被釋放。
2.千萬不要寫一個native函數來保存一個局部引用在靜態變量或全局變量中並期望在以後的函數調用中使用。
// instance是一個局部引用,不能使用1中的方式進行賦值。當該函數返回後,將釋放
// 包含在this->instance變量中的局部引用
JniCallbackHelper::JniCallbackHelper(JavaVM *pVM, _JNIEnv *pEnv, jobject instance) {
this->jniVm = pVM;
this->env = pEnv;
// this->instance = instance; // 1.錯誤示範
// 2. jobject一旦涉及到跨方法,跨線程,需要創建全局引用
this->instance = env->NewGlobalRef(instance);
jclass clz = env->GetObjectClass(instance);
jmd_prepared = env->GetMethodID(clz, "onPrepared", "()V");
}
JNIEnv跨線程問題
1.JNIEnv是當前線程的上下文,如果在C++子線程中想要調用JAVA層的代碼,那麼需要使用JavaVM ->AttachCurrentThread(&env_child, 0);來創建一個子線程對應的JNIEnv,然後再調用JAVA層的代碼。
// 子線程 JavaVM *jniVm
JNIEnv * env_child;
jniVm->AttachCurrentThread(&env_child, 0);
env_child->CallVoidMethod(instance, jmd_prepared);
jniVm->DetachCurrentThread();
JavaVM初始化問題
jint JNI_OnLoad(JavaVM* jvm, void* reserved) {
JavaVm *javaVM = jvm;
return JNI_VERSION_1_6;
}