Android ART 的初始化和啟動

來源:互聯網
上載者:User

標籤:android art

ART的初始化
 下面我們從JNI_GetDefaultJavaVMInitArgs(),JNI_CreateJavaVM()和JNI_GetCreatedJavaVMs()三個函數入手來瞭解ART的初始化過程。這三個函數的代碼位於jni_internal.cc中。
 JNI_GetDefaultJavaVMInitArgs()函數在ART中沒有作為,只是返回JNI_ERR。如下所示:
 extern "C" jintJNI_GetDefaultJavaVMInitArgs(void* ) {
   return JNI_ERR;
 }
 JNI_GetCreatedJavaVMs()函數用來返回在Runtime中儲存的JavaVMExt的指標,函數代碼如下所示:
 extern "C" jint JNI_GetCreatedJavaVMs(JavaVM**vms, jsize, jsize* vm_count) {
   Runtime* runtime =Runtime::Current();
   if (runtime == NULL) {
    *vm_count = 0;
   } else {
    *vm_count = 1;
    vms[0] = runtime->GetJavaVM();
   }
   return JNI_OK;
 }
 Runtime的GetJavaVM()函數只是返回了Runtime類的成員變數java_vm_,如下所示。
 JavaVMExt* GetJavaVM() const {
    return java_vm_;
 }
java_vm_是JavaVMExt類型的指標,定義如下:
  JavaVMExt* java_vm_;


 理解了兩個簡單的函數後,我們再來分析JNI_CreateJavaVM()函數,代碼如下:
 extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm,JNIEnv** p_env, void* vm_args) {
   const JavaVMInitArgs* args =static_cast(vm_args);
   // 檢查JNI的版本
   if(IsBadJniVersion(args->version)) {
    LOG(ERROR) << "Bad JNI version passed to CreateJavaVM: "<< args->version;
    return JNI_EVERSION;
   }
   // 儲存啟動參數到options中。
   Runtime::Optionsoptions;
   for (int i = 0; i <args->nOptions; ++i) {
    JavaVMOption* option = &args->options[i];
    options.push_back(std::make_pair(std::string(option->optionString),option->extraInfo));
   }
   bool ignore_unrecognized =args->ignoreUnrecognized;
   if (!Runtime::Create(options,ignore_unrecognized)) { // 建立虛擬機器
    return JNI_ERR;
   }
   Runtime* runtime =Runtime::Current();
   bool started =runtime->Start();      //啟動虛擬機器
   if (!started) {
    delete Thread::Current()->GetJniEnv();
    delete runtime->GetJavaVM();
    return JNI_ERR; // 啟動失敗,方法
   }
   *p_env =Thread::Current()->GetJniEnv();
   *p_vm =runtime->GetJavaVM();
   return JNI_OK;
 }
 JNI_CreateJavaVM()函數中調用Runtime的Create()函數來建立虛擬機器,然後調用start()函數來啟動它。在ART中,Runtime對象的地位和Dalvik中的DvmGlobals對象gDVm類似,包含了所有重要的變數。
下面我們繼續分析Create()函數:
 bool Runtime::Create(const Options& options,bool ignore_unrecognized) {
   if (Runtime::instance_ !=NULL) {
    return false;  //只能建立一個Runtime執行個體
   }
  InitLogging(NULL);  // Calls Locks::Init() as aside effect.
   instance_ = newRuntime;  // 建立了Runtime類的執行個體
   if(!instance_->Init(options, ignore_unrecognized)){ // 初始化Runtime對象
    delete instance_;
    instance_ = NULL;
    return false;
   }
   return true;
 }
 Runtime的Create()函數中建立了Runtime對象,並調用它的Init()函數進行初始化。函數代碼如下:
 bool Runtime::Init(const Options&raw_options, bool ignore_unrecognized) {
   UniquePtroptions(ParsedOptions::Create(raw_options,
 ignore_unrecognized));
   ......
   QuasiAtomic::Startup();
  Monitor::Init(options->lock_profiling_threshold_,
 options->hook_is_sensitive_thread_);
   host_prefix_ =options->host_prefix_;
   boot_class_path_string_ =options->boot_class_path_string_;
   ... // 更多的賦值語句
   monitor_list_ = newMonitorList;
   thread_list_ = newThreadList;
   intern_table_ = newInternTable;
   if(options->interpreter_only_) {
    GetInstrumentation()->ForceInterpretOnly();
   }
   // 建立堆(Heap)對象
   heap_ = newgc::Heap(options->heap_initial_size_,
                       options->heap_growth_limit_,
                       ......);
   BlockSignals();
  InitPlatformSignalHandlers();
   // 建立JavaVMExt對象
   java_vm_ = new JavaVMExt(this,options.get());
  // 將當前的主線程變成一個“Java” 線程
  Thread::Startup(); 
   Thread* self =Thread::Attach("main", false, NULL, false); 
  self->TransitionFromSuspendedToRunnable();
  GetHeap()->EnableObjectValidation();
   if(GetHeap()->GetContinuousSpaces()[0]->IsImageSpace()) {
    class_linker_ = ClassLinker::CreateFromImage(intern_table_);
   } else {
    class_linker_ =ClassLinker::CreateFromCompiler(*options->boot_class_path_, intern_table_);
   }
   ......
   return true;
 }
 Init()函數最重要的工作是建立了Heap對象和ClassLinker對象。我們只要將ART和Dalvik對比一下就可以理解,因為ART模式下並不需要去解析和執行位元組碼,所以它的工作比Dalivk要少很多。即使應用已經編譯成了可執行代碼,但是同樣也要支援記憶體回收功能,所以Heap模組還是必不可少的。Art的Heap模組的功能幾乎和Dalvik中的相同,記憶體回收的演算法也是標誌並清除法,不過代碼的實現更加晦澀,所以本書不打算再分析一遍Art的Heap演算法了。
 ART雖然不用去裝載和執行位元組碼,但是還是要保留所有Java類的資訊,Java程式和C++程式除了記憶體管理方式不同外,最大的區別是Java程式能夠動態擷取各種類的資訊,包括方法,變數等。所以ART中同樣也要提供這些功能,否則編譯出來的程式也無法使用。ClassLinker類的作用就是在ART內部提供各種Java類的解析功能。

ART開始運行
 初始化完成之後,接下來是調用Runtime的start()函數開始運行,函數代碼如下:
 bool Runtime::Start() {
   VLOG(startup) <<"Runtime::Start entering";
   Thread* self =Thread::Current();
  self->TransitionFromRunnableToSuspended(kNative);
   started_ = true;
  InitNativeMethods()   //初始化本地的JNI方法
   InitThreadGroups(self);
   Thread::FinishStartup();
   if (is_zygote_) {
      if (!InitZygote()) {
          return false;
      }
   } else {
      DidForkFromZygote();
   }
  StartDaemonThreads();  //調用java.lang.Daemons的start方法
   system_class_loader_ =CreateSystemClassLoader(); //建立一個ClassLoader對象
  self->GetJniEnv()->locals.AssertEmpty();
   VLOG(startup) <<"Runtime::Start exiting";
   finished_starting_ =true;
   return true;
 }
 Start()方法中會調用InitNativeMethods()來初始化本地的JNI方法,ART中也同樣支援JNI函數,不過ART中對部分系統的JNI函數進行了重寫,但是實現原理和Dalvik中的沒有太大區別,而大部分其他模組的JNI函數還是保持不變。調用InitNativeMethods()方法後這些JNI函數就可以使用了。
接下來如果是在Zygote進程中,則會調用InitZygote()函數來進行初始化,這個函數的實現和Dalvik中的幾乎一樣,主要工作是設定進程的groupid,以及mountrootfs檔案系統到根目錄。如果不是Zygote進程,則調用DidForkFromZygote()函數,這個函數主要工作是調用Heap對象的CreateThreadPool()函數來建立線程池。
最後Start()函數中調用了StartDaemonThreads()函數,這個函數的工作是調用Java類Daemons的start()方法來啟動一些Deamon線程,這些Deamon前面我們已經分析過了。這個過程實際上和Dalvik啟動時完成的最後一項工作相同。
對比Dalivk啟動時需要完成的工作,ART是相當的簡單了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.