乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      認(rèn)識*.so里的JNI_OnLoad()函數(shù)

       lifei_szdz 2012-12-11

      認(rèn)識*.so里的JNI_OnLoad()函數(shù)

      當(dāng)Android VM(Virtual Machine)執(zhí)行到C組件(*so文件)里的System.loadLibrary()函數(shù)時,首先會去執(zhí)行C組件里的JNI_OnLoad()函數(shù)。它的用途有二:

      1.       告訴VMC組件使用那一個JNI版本。如果你的*.so文件沒有提供JNI_OnLoad()函數(shù),VM會默認(rèn)該*.so檔是使用最老的JNI 1.1版本。由于新版的JNI做了許多擴充,如果需要使用JNI的新版功能,例如JNI 1.4 java.nio.ByteBuffer, 就必須藉由JNI_OnLoad()函數(shù)來告知VM。

      2.       由于VM執(zhí)行到System.loadLibrary()函數(shù)時,就會立即先呼叫JNI_OnLoad(),所以C組件的開發(fā)者可以藉由JNI_OnLoad()來進(jìn)行C組件內(nèi)的初期值之設(shè)定(Initialization)。

       

      例如,在Android/system/lib/libmedia_jni.so檔案里,就提供了JNI_OnLoad()函數(shù),其程序代碼片段為:

       

      //#define LOG_NDEBUG 0

      #define LOG_TAG "MediaPlayer-JNI"

      ………

      jint JNI_OnLoad(JavaVM* vm, void* reserved)

      {

          JNIEnv* env = NULL;

          jint result = -1;

       

          if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {

              LOGE("ERROR: GetEnv failed\n");

              goto bail;

          }

          assert(env != NULL);

          if (register_android_media_MediaPlayer(env) < 0) {

              LOGE("ERROR: MediaPlayer native registration failed\n");

              goto bail;

          }

          if (register_android_media_MediaRecorder(env) < 0) {

              LOGE("ERROR: MediaRecorder native registration failed\n");

              goto bail;

          }

          if (register_android_media_MediaScanner(env) < 0) {

              LOGE("ERROR: MediaScanner native registration failed\n");

              goto bail;

          }

          if (register_android_media_MediaMetadataRetriever(env) < 0) {

              LOGE("ERROR: MediaMetadataRetriever native registration failed\n");

              goto bail;

          }

          /* success -- return valid version number */

          result = JNI_VERSION_1_4;

      bail:

          return result;

      }

      // KTHXBYE

       

          此函數(shù)回傳JNI_VERSION_1_4值給VM,于是VM知道了其所使用的JNI版本了。此外,它也做了一些初期的動作(可呼叫任何本地函數(shù)),例如指令:

       

         if (register_android_media_MediaPlayer(env) < 0) {

              LOGE("ERROR: MediaPlayer native registration failed\n");

              goto bail;

          }

       

      就將此組件提供的各個本地函數(shù)(Native Function)登記到VM里,以便能加快后續(xù)呼叫本地函數(shù)之效率。

          JNI_OnUnload()函數(shù)JNI_OnLoad()相對應(yīng)的。在加載C組件時會立即呼叫JNI_OnLoad()來進(jìn)行組件內(nèi)的初期動作;而當(dāng)VM釋放該C組件時,則會呼叫JNI_OnUnload()函數(shù)來進(jìn)行善后清除動作。當(dāng)VM呼叫JNI_OnLoad()JNI_Unload()函數(shù)時,都會將VM的指標(biāo)(Pointer)傳遞給它們,其參數(shù)如下:

       

      jint JNI_OnLoad(JavaVM* vm, void* reserved)

      {

            ………

      }

       

      jint JNI_OnUnload(JavaVM* vm, void* reserved)

      {

            ………

      }

       

      JNI_OnLoad()函數(shù)里,就透過VM之指標(biāo)而取得JNIEnv之指標(biāo)值,并存入env指針變量里,如下述指令:

       

      jint JNI_OnLoad(JavaVM* vm, void* reserved)

      {

          JNIEnv* env = NULL;

          jint result = -1;

       

          if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {

              LOGE("ERROR: GetEnv failed\n");

              goto bail;

          }

       

          由于VM通常是多執(zhí)行緒(Multi-threading)的執(zhí)行環(huán)境。每一個執(zhí)行緒在呼叫JNI_OnLoad()時,所傳遞進(jìn)來的JNIEnv指標(biāo)值都是不同的。為了配合這種多執(zhí)行緒的環(huán)境,C組件開發(fā)者在撰寫本地函數(shù)時,可藉由JNIEnv指標(biāo)值之不同而避免執(zhí)行緒的數(shù)據(jù)沖突問題,才能確保所寫的本地函數(shù)能安全地在Android多執(zhí)行緒VM 里安全地執(zhí)行?;谶@個理由,當(dāng)在呼叫C組件的函數(shù)時,都會將JNIEnv指標(biāo)值傳遞給它,如下:

      jint JNI_OnLoad(JavaVM* vm, void* reserved)

      {

      JNIEnv* env = NULL;

        ……….

          if (register_android_media_MediaPlayer(env) < 0) {

             …….

          }

           }

      JNI_OnLoad()呼叫register_android_media_MediaPlayer(env)函數(shù)時,就將env指標(biāo)值傳遞過去。如此,在register_android_media_MediaPlayer()函數(shù)就能藉由該指標(biāo)值而區(qū)別不同的執(zhí)行緒,以便化解數(shù)據(jù)沖突的問題。

            例如,在register_android_media_MediaPlayer()函數(shù)里,可撰寫下述指令:

              if ((*env)->MonitorEnter(env, obj) != JNI_OK) {

                   ………

       }

       

          查看是否已經(jīng)有其它執(zhí)行緒進(jìn)入此對象,如果沒有,此執(zhí)行緒就進(jìn)入該對象里執(zhí)行了。還有,也可撰寫下述指令:

       

               if ((*env)->MonitorExit(env, obj) != JNI_OK) {

                    ………

                }

       

      查看是否此執(zhí)行緒正在此對象內(nèi)執(zhí)行,如果是,此執(zhí)行緒就會立即離開。

       

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多