<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                AppRuntime類的聲明和實現均在App_main.cpp中,它是從AndroidRuntime類派生出來的,圖4-1顯示了這兩個類的關系和一些重要函數: :-: ![](http://img.blog.csdn.net/20150802153752007?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 圖4-1 AppRuntime和AndroidRuntime的關系 由上圖我們可知: - AppRuntime重載了onStarted、onZygoteInit和onExit函數。 前面的代碼中調用了AndroidRuntime的start函數,由圖4-1可知,這個start函數使用的是基類AndroidRuntime的start,我們來分析一下它,注意它的調用參數。 **AndroidRuntime.cpp** ~~~ void AndroidRuntime::start(const char*className, const bool startSystemServer) { //className的值是"com.android.internal.os.ZygoteInit" //startSystemServer的值是true char*slashClassName = NULL; char*cp; JNIEnv* env; blockSigpipe();//處理SIGPIPE信號 ...... constchar* rootDir = getenv("ANDROID_ROOT"); if (rootDir == NULL) { //如果環境變量中沒有ANDROID_ROOT,則新增該變量,并設置值為“/system" rootDir = “/system"; ...... setenv("ANDROID_ROOT", rootDir, 1); } //① 創建虛擬機 if(startVm(&mJavaVM, &env) != 0) goto bail; //②注冊JNI函數 if(startReg(env) < 0) { goto bail; } jclassstringClass; jobjectArray strArray; jstring classNameStr; jstring startSystemServerStr; stringClass = env->FindClass("java/lang/String"); //創建一個有兩個元素的String數組,即Java代碼 String strArray[] = new String[2] strArray = env->NewObjectArray(2, stringClass, NULL); classNameStr = env->NewStringUTF(className); //設置第一個元素為"com.android.internal.os.ZygoteInit" env->SetObjectArrayElement(strArray, 0, classNameStr); startSystemServerStr = env->NewStringUTF(startSystemServer ? "true" : "false"); //設置第二個元素為"true",注意這兩個元素都是String類型,即字符串。 env->SetObjectArrayElement(strArray, 1, startSystemServerStr); jclassstartClass; jmethodID startMeth; slashClassName = strdup(className); /* 將字符串“com.android.internal.os.ZygoteInit”中的“. ”換成“/”, 這樣就變成了“com/android/internal/os/ZygoteInit”,這個名字符合JNI規范, 我們可將其簡稱為ZygoteInit類。 */ for(cp = slashClassName; *cp != '\0'; cp++) if(*cp == '.') *cp = '/'; startClass = env->FindClass(slashClassName); ...... //找到ZygoteInit類的static main函數的jMethodId。 startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V"); ...... /* ③通過JNI調用Java函數,注意調用的函數是main,所屬的類是 com.android.internal.os.ZygoteInit,傳遞的參數是 “com.android.internal.os.ZygoteInit true”, 調用ZygoteInit的main函數后,Zygote便進入了Java世界! 也就是說,Zygote是開創Android系統中Java世界的盤古。 */ env->CallStaticVoidMethod(startClass,startMeth, strArray); //Zygote退出,在正常情況下,Zygote不需要退出。 if(mJavaVM->DetachCurrentThread() != JNI_OK) LOGW("Warning: unable to detach main thread\n"); if(mJavaVM->DestroyJavaVM() != 0) LOGW("Warning: VM did not shut down cleanly\n"); bail: free(slashClassName); } ~~~ 通過上面的分析,我們找到了三個關鍵點,它們共同組成了開創Android系統中Java世界的三部曲。現在讓我們來具體地觀察它們。 1. 創建虛擬機——startVm 我們先看三部曲中的第一部:startVm,這個函數沒有特別之處,就是調用JNI的虛擬機創建函數,但是虛擬機創建時的一些參數卻是在startVm中被確定的,其代碼如下所示: **AndroidRuntime.cpp** ~~~ int AndroidRuntime::startVm(JavaVM** pJavaVM,JNIEnv** pEnv) { //這個函數絕大部分代碼都是設置虛擬機的參數,我們只分析其中的兩個。 /* 下面的代碼是用來設置JNI check選項的。JNIcheck 指的是Native層調用JNI函數時, 系統所做的一些檢查工作。例如調用NewUTFString函數時,系統會檢查傳入的字符串是不是符合 UTF-8的要求。JNI check還能檢查資源是否正確釋放。但這個選項也有其副作用,比如: 1)因為檢查工作比較耗時,所以會影響系統運行速度。 2)有些檢查過于嚴格,例如上面的字符串檢查,一旦出錯,則調用進程就會abort。 所以,JNI check選項一般只在調試的eng版設置,而正式發布的user版則不設置該選項。 下面這幾句代碼就控制著是否啟用JNI check,這是由系統屬性決定的,eng版如經過特殊配置,也可以去掉JNI check。 */ property_get("dalvik.vm.checkjni",propBuf, ""); if(strcmp(propBuf, "true") == 0) { checkJni = true; } elseif (strcmp(propBuf, "false") != 0) { property_get("ro.kernel.android.checkjni",propBuf, ""); if(propBuf[0] == '1') { checkJni = true; } } ...... /* 設置虛擬機heapsize,默認為16MB。絕大多數廠商都會修改這個值,一般是32MB。 heapsize不能設置過小,否則在操作大尺寸的圖片時無法分配所需內存。 這里有一個問題,即heapsize既然是系統級的屬性,那么能否根據不同應用程序的需求來進行動 態調整?我開始也考慮過能否實現這一構想,不過希望很快就破滅了。對這一問題,我們將在拓展 部分深入討論。 */ strcpy(heapsizeOptsBuf, "-Xmx"); property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m"); opt.optionString = heapsizeOptsBuf; mOptions.add(opt); if(checkJni) { opt.optionString ="-Xcheck:jni"; mOptions.add(opt); //JNIcheck中的資源檢查,系統中創建的Globalreference個數不能超過2000 opt.optionString = "-Xjnigreflimit:2000"; mOptions.add(opt); } // 調用JNI_CreateJavaVM創建虛擬機,pEnv返回當前線程的JNIEnv變量 if(JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) { LOGE("JNI_CreateJavaVM failed\n"); goto bail; } result= 0; bail: free(stackTraceFile); returnresult; } ~~~ 關于dalvik虛擬機的詳細參數,讀者可以參見Dalvik/Docs/Dexopt.html中的說明。這個Docs目錄下的內容,或許可幫助我們更深入地了解dalvik虛擬機。 2. 注冊JNI函數——startReg 前面已經介紹了如何創建虛擬機,下一步則需要給這個虛擬機注冊一些JNI函數。正是因為后續Java世界用到的一些函數是采用native方式來實現的,所以才必須提前注冊這些函數。 下面我們來看看這個startReg函數,代碼如下所示: **AndroidRuntime.cpp** ~~~ int AndroidRuntime::startReg(JNIEnv* env) { //注意,設置Thread類的線程創建函數為javaCreateThreadEtc //它的作用,將在對Thread分析一部分(第5章)中做詳細介紹。 androidSetCreateThreadFunc((android_create_thread_fn)javaCreateThreadEtc); env->PushLocalFrame(200); //注冊jni函數,gRegJNI是一個全局數組。 if(register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) { env->PopLocalFrame(NULL); return -1; } env->PopLocalFrame(NULL); //下面這句話應當是“碼農”休閑時的小把戲。在日新月異的IT世界中,它現已絕對是“文物”了。 //createJavaThread("fubar", quickTest, (void*)"hello"); return0; } ~~~ 我們來看看register_jni_procs,代碼如下所示: **AndroidRuntime.cpp** ~~~ static int register_jni_procs(const RegJNIRecarray[], size_t count, JNIEnv* env) { for(size_t i = 0; i < count; i++) { if(array[i].mProc(env) < 0) {//僅僅是一個封裝,調用數組元素的mProc函數 return -1; } } return 0; } ~~~ 上面的函數調用的不過是數組元素的mProc函數,再讓我們直接看看這個全局數組的gRegJNI變量。 **AndroidRuntime.cpp::gRegJNI聲明** ~~~ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_debug_JNITest), REG_JNI(register_com_android_internal_os_RuntimeInit), REG_JNI(register_android_os_SystemClock), REG_JNI(register_android_util_EventLog), REG_JNI(register_android_util_Log), ...//共有100項 }; ~~~ REG_JNI是一個宏,宏里邊包括的就是那個mProc函數,這里,我們來分析一個例子。 **android_debug_JNITest.cpp** ~~~ int register_android_debug_JNITest(JNIEnv* env) { //為android.debug.JNITest類注冊它所需要的JNI函數 returnjniRegisterNativeMethods(env, "android/debug/JNITest", gMethods,NELEM(gMethods)); } ~~~ 哦,原來mProc就是為Java類注冊JNI函數! 至此,虛擬機已創建好,JNI函數也已注冊,下一步就要分析CallStaticVoidMethod了。通過這個函數,我們將進入Android所精心打造的Java世界,而且最佳情況是,永遠也不回到Native世界。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看