1. 程式人生 > >Art下DexClassLoader將dex轉化為oat檔案格式的過程

Art下DexClassLoader將dex轉化為oat檔案格式的過程

經過看原始碼DexClassLoader最終會呼叫DexFile類中的native函式openDexFileNative。

下面來看看openDexFileNative函式做了什麼。

openDexFileNative函式在art\runtime\native\dalvik_system_DexFile.cc檔案中下面的程式碼匯出了openDexFileNative符號。

static JNINativeMethod gMethods[] = {
  NATIVE_METHOD(DexFile, closeDexFile, "(I)V"),
  NATIVE_METHOD(DexFile, defineClassNative, "(Ljava/lang/String;Ljava/lang/ClassLoader;I)Ljava/lang/Class;"),
  NATIVE_METHOD(DexFile, getClassNameList, "(I)[Ljava/lang/String;"),
  NATIVE_METHOD(DexFile, isDexOptNeeded, "(Ljava/lang/String;)Z"),
  NATIVE_METHOD(DexFile, openDexFileNative, "(Ljava/lang/String;Ljava/lang/String;I)I"),
};

通過觀察上面的全域性變數可以發現,openDexFileNative所代表的函式是DexFile_openDexFileNative。

在DexFile_openDexFileNative函式中,首先呼叫DexFile::GetChecksum函式獲得了zip檔案或dex檔案的校驗和,如果獲得校驗和成功將校驗和儲存在區域性變數dex_location_checksum中。

DexFile::GetChecksum(dex_location, &dex_location_checksum)

如果outputName不為NULL,則將執行下面的程式碼進行dex到oat的轉換。
std::string oat_location(outputName.c_str());
dex_file = linker->FindOrCreateOatFileForDexLocation(dex_location, dex_location_checksum, oat_location);

-------------------------------------------------------------------


FindOrCreateOatFileForDexLocation函式是ClassLinker類的成員函式,下面來看看FindOrCreateOatFileForDexLocation函式做了什麼。

ClassLinker::FindOrCreateOatFileForDexLocation函式呼叫了ClassLinker::FindOrCreateOatFileForDexLocationLocked函式。

return FindOrCreateOatFileForDexLocationLocked(dex_location, dex_location_checksum, oat_location);
-------------------------------------------------------------------
ClassLinker::FindOrCreateOatFileForDexLocationLocked函式中。

通過呼叫ClassLinker::FindDexFileInOatLocation函式判斷dex檔案是否已經優化為oat檔案。

// Check if we already have an up-to-date output file
const DexFile* dex_file = FindDexFileInOatLocation(dex_location,
                                                     dex_location_checksum,
                                                     oat_location);

如果dex未被優化為oat檔案,則呼叫ClassLinker::GenerateOatFile函式將dex轉換為oat。
GenerateOatFile(dex_location, scoped_flock.GetFile().Fd(), oat_location)

ClassLinker::GenerateOatFile函式中fork了一個子程序,在子程序中呼叫了dex2oat進行dex到oat的轉換,並且父程序等待子程序執行的結束。
// fork and exec dex2oat
pid_t pid = fork();

    execl(dex2oat, dex2oat,
          "--runtime-arg", "-Xms64m",
          "--runtime-arg", "-Xmx64m",
          "--runtime-arg", "-classpath",
          "--runtime-arg", class_path,
          "--runtime-arg", oat_compiler_filter_option,
#if !defined(ART_TARGET)
          "--host",
#endif
          boot_image_option,
          dex_file_option,
          oat_fd_option,
          oat_location_option,
          NULL);

ClassLinker::GenerateOatFile函式執行完成後,又呼叫了oat_dex_file->OpenDexFile()函式開啟在記憶體中的dex檔案。
const DexFile* result = oat_dex_file->OpenDexFile();


至此,完成了dex到oat的轉換。