国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

NDK學習( 三),多線程與異步回調

2019-11-06 09:55:16
字體:
來源:轉載
供稿:網友
場景:在java中傳遞任意類型參數,在JNI中新開子線程,將傳入的參數處理后回調Java中的方法技術點:1、在JNI中新開子線程并傳遞參數2、在子線程中回調Java方法(誤區:JNIEnv指針可以共享)對于技術點1,可參考一般的C++開發教程,一般創建子線程的方法有:通過pthread_createC++11中thread的用法參考:http://stackoverflow.com/questions/23872663/how-to-start-a-new-thread-from-jni另外要注意的是傳遞的參數應當是堆內存中的指針,或者是全局變量,對于局部變量,可能在子線程中調用時已經失效。對于技術點2,需要注意的是JNIEnv *這類指針是無法在線程間共享的,參考JNI文檔。參考:http://stackoverflow.com/questions/13383823/native-multithreading-and-jni步驟:在JNI_OnLoad或者Java調用的native方法中緩存JavaVM*,JavaVM*指針是唯一在線程間可以共享的。在子線程的native方法中調用AttachCurrentThread ,獲取JNIEnv*指針。通過JavaVM*和JNIEnv*找到你需要的jclasses,jobjects,jmethodIDs,它們不能在線程間共享。如果需要,將jclasses,jobjects轉換為全局變量,jmethodIDs不需要轉換,因為它不是對象。在JNI_OnUnlaod時刪除全局變量這類引用,當你不再需要時。理解JNI_OnLoad、JNI_OnUnload參考:http://docs.Oracle.com/javase/1.5.0/docs/guide/jni/spec/invocation.html#JNI_OnLoad當native lib被加載(如System.loadLibrary()執行后),虛擬機會執行JNI_OnLoad,該方法必須返回當前JNI版本號。如果native lib不exportJNI_OnLoad方法,虛擬機認為lib只需要JNI_VERSION_1_1.如果返回的版本號不能被識別,該lib將不能被加載。當包含native lib的類加載器被垃圾回收器回收,JNI_OnUnload會被調用。該方法可用來清理不再需要的指針。Java代碼:public native void asyncCallBack(String str);//執行后向native lib傳入字符串native代碼:extern "C" {JavaVM* javaVM; //定義要全局共享的虛擬機指針jobject jinstance; //定義要共享的Java對象JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* jvm, void* reserved){javaVM = jvm; //將全局虛擬機指針賦值JNIEnv* env = NULL;jint result = -1;//獲取JNI版本if (jvm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK){LOGE("GetEnv failed!");return result;}LOGE("JNI_VERSION:%d",JNI_VERSION_1_4);return JNI_VERSION_1_4;}//線程函數void* runAsync(void* args) {const char* chars = (const char*) args;JNIEnv *env = NULL;//Attach主線程if (javaVM->AttachCurrentThread(&env, NULL) != JNI_OK) {LOGE("%s: AttachCurrentThread() failed", __FUNCTION__);return NULL;}if (env != NULL) {LOGE("jnienv* obtained");}else {return NULL;}LOGE("runAsync chars:%s", chars);jclass jclass1 = env->GetObjectClass(jinstance);if(jclass1==NULL){LOGE("sub thread : failed get class");return NULL;}else{LOGE("sub thread : find class");}jmethodID jmethodID =env->GetMethodID(jclass1,"callback","(Ljava/lang/String;)V");if(jmethodID==NULL){LOGE("sub thread : failed get jmethodID");return NULL;}else{LOGE("sub thread : find jmethodID");}string str =chars;string str2 = " from native";str.append(str2);jstring jstr=env->NewStringUTF(str.c_str());env->CallVoidMethod(jinstance,jmethodID,jstr);env->DeleteGlobalRef(jinstance);//刪除全局引用if(javaVM!=NULL){javaVM=NULL;LOGE("release JavaVM*");}if(jinstance!=NULL){jinstance=NULL;LOGE("release jinstance*");}LOGE("sub thread:task finish");}JNIEXPORT void JNICALLJava_dev_mars_jnidemo_NativeThread_asyncCallBack(JNIEnv *env, jobject instance,jstring jstr) {const char* chars = env->GetStringUTFChars(jstr,0);LOGE("Java_dev_mars_jnidemo_NativeThread_asyncCallBack pass parameter:%s",chars);//將jobject轉換為全局變量,因為jclass、jobject也不能在線程間共享jinstance = env->NewGlobalRef(instance);pthread_t thread_1;pthread_create(&thread_1,NULL,runAsync,(void*)chars);}}小結:jobject、jclass、jmethodID這些類型無法在線程間共享,需要轉換為全局變量。本例中在JNI接口線程中將jobject轉換為全局變量,在子線程通過JavaVM*獲取JNIEnv*,并通過全局變量jobect獲取jclass,從而得到jmethod。native調用java方法的函數主要有三種:參考:http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html#wp16656NativeType Call<type>Method(JNIEnv *env, jobject obj,jmethodID methodID, ...);NativeType Call<type>MethodA(JNIEnv *env, jobject obj,jmethodID methodID, const jvalue *args);NativeType Call<type>MethodV(JNIEnv *env, jobject obj,jmethodID methodID, va_list args);通過觀察發現,Method、MethodA、MethodV所帶的參數類型不同,其中<type>是回調的返回類型。創建jobject的全局引用通過 env->NewGlobalRef(instance);回調完釋放全局引用通過JNIEnv*的 env->DeleteGlobalRef(jinstance);參考:http://journals.ecs.soton.ac.uk/java/tutorial/native1.1/implementing/sync.html如本文有任何問題歡迎指出,謝謝
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 木里| 三原县| 蚌埠市| 苏尼特右旗| 察雅县| 普陀区| 临武县| 黑龙江省| 申扎县| 和政县| 佛坪县| 黎平县| 苍梧县| 常德市| 丰县| 安宁市| 龙泉市| 镇巴县| 大田县| 河北省| 大余县| 兴仁县| 兴安盟| 怀集县| 合水县| 江华| 临猗县| 吉安市| 宝清县| 新巴尔虎右旗| 通山县| 广饶县| 江山市| 淳化县| 临清市| 南投市| 北安市| 翁牛特旗| 盐亭县| 托克逊县| 洪湖市|