Art下DexClassLoader將dex轉化為oat檔案格式的過程
阿新 • • 發佈:2019-01-25
經過看原始碼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的轉換。