三、oat_file_assistant.cc#MakeUpToDate 函数分析
在 oat_file_assistant.cc#MakeUpToDate 函数中 , 最终调用了 GenerateOatFileNoChecks 函数 , 执行下一步操作 ;
oat_file_assistant.cc#MakeUpToDate 函数源码 :
OatFileAssistant::ResultOfAttemptToUpdate OatFileAssistant::MakeUpToDate(bool profile_changed, std::string* error_msg) { CompilerFilter::Filter target; if (!GetRuntimeCompilerFilterOption(&target, error_msg)) { return kUpdateNotAttempted; } OatFileInfo& info = GetBestInfo(); switch (info.GetDexOptNeeded(target, profile_changed)) { case kNoDexOptNeeded: return kUpdateSucceeded; // TODO: 现在,不要为我们打电话的各种方式而烦恼 // dex2oat生成oat文件。始终生成oat文件,就像它 // KDEX2O是从头开始的。 case kDex2OatFromScratch: case kDex2OatForBootImage: case kDex2OatForRelocation: case kDex2OatForFilter: // ★ 核心跳转 return GenerateOatFileNoChecks(info, target, error_msg); } UNREACHABLE(); }
源码路径 : /art/runtime/oat_file_assistant.cc#MakeUpToDate
四、oat_file_assistant.cc#GenerateOatFileNoChecks 函数分析
先判断 Dex2Oat 当前是否可用 , 如果不可用 , 直接返回 ;
!runtime->IsDex2OatEnabled()
oat_file_assistant.cc#GenerateOatFileNoChecks 函数源码 :
OatFileAssistant::ResultOfAttemptToUpdate OatFileAssistant::GenerateOatFileNoChecks( OatFileAssistant::OatFileInfo& info, CompilerFilter::Filter filter, std::string* error_msg) { CHECK(error_msg != nullptr); Runtime* runtime = Runtime::Current(); // 判断 Dex2Oat 当前是否可用 , 如果不可用 , 直接返回 if (!runtime->IsDex2OatEnabled()) { *error_msg = "Generation of oat file for dex location " + dex_location_ + " not attempted because dex2oat is disabled."; return kUpdateNotAttempted; } if (info.Filename() == nullptr) { *error_msg = "Generation of oat file for dex location " + dex_location_ + " not attempted because the oat file name could not be determined."; return kUpdateNotAttempted; } const std::string& oat_file_name = *info.Filename(); const std::string& vdex_file_name = GetVdexFilename(oat_file_name); // dex2oat ignores missing dex files and doesn't report an error. // Check explicitly here so we can detect the error properly. // TODO: Why does dex2oat behave that way? struct stat dex_path_stat; if (TEMP_FAILURE_RETRY(stat(dex_location_.c_str(), &dex_path_stat)) != 0) { *error_msg = "Could not access dex location " + dex_location_ + ":" + strerror(errno); return kUpdateNotAttempted; } // If this is the odex location, we need to create the odex file layout (../oat/isa/..) if (!info.IsOatLocation()) { if (!PrepareOdexDirectories(dex_location_, oat_file_name, isa_, error_msg)) { return kUpdateNotAttempted; } } // Set the permissions for the oat and the vdex files. // The user always gets read and write while the group and others propagate // the reading access of the original dex file. mode_t file_mode = S_IRUSR | S_IWUSR | (dex_path_stat.st_mode & S_IRGRP) | (dex_path_stat.st_mode & S_IROTH); std::unique_ptr<File> vdex_file(OS::CreateEmptyFile(vdex_file_name.c_str())); if (vdex_file.get() == nullptr) { *error_msg = "Generation of oat file " + oat_file_name + " not attempted because the vdex file " + vdex_file_name + " could not be opened."; return kUpdateNotAttempted; } if (fchmod(vdex_file->Fd(), file_mode) != 0) { *error_msg = "Generation of oat file " + oat_file_name + " not attempted because the vdex file " + vdex_file_name + " could not be made world readable."; return kUpdateNotAttempted; } std::unique_ptr<File> oat_file(OS::CreateEmptyFile(oat_file_name.c_str())); if (oat_file.get() == nullptr) { *error_msg = "Generation of oat file " + oat_file_name + " not attempted because the oat file could not be created."; return kUpdateNotAttempted; } if (fchmod(oat_file->Fd(), file_mode) != 0) { *error_msg = "Generation of oat file " + oat_file_name + " not attempted because the oat file could not be made world readable."; oat_file->Erase(); return kUpdateNotAttempted; } std::vector<std::string> args; args.push_back("--dex-file=" + dex_location_); args.push_back("--output-vdex-fd=" + std::to_string(vdex_file->Fd())); args.push_back("--oat-fd=" + std::to_string(oat_file->Fd())); args.push_back("--oat-location=" + oat_file_name); args.push_back("--compiler-filter=" + CompilerFilter::NameOfFilter(filter)); // ★ 核心跳转 if (!Dex2Oat(args, error_msg)) { // Manually delete the oat and vdex files. This ensures there is no garbage // left over if the process unexpectedly died. vdex_file->Erase(); unlink(vdex_file_name.c_str()); oat_file->Erase(); unlink(oat_file_name.c_str()); return kUpdateFailed; } if (vdex_file->FlushCloseOrErase() != 0) { *error_msg = "Unable to close vdex file " + vdex_file_name; unlink(vdex_file_name.c_str()); return kUpdateFailed; } if (oat_file->FlushCloseOrErase() != 0) { *error_msg = "Unable to close oat file " + oat_file_name; unlink(oat_file_name.c_str()); return kUpdateFailed; } // Mark that the odex file has changed and we should try to reload. info.Reset(); return kUpdateSucceeded; }
源码路径 : /art/runtime/oat_file_assistant.cc#GenerateOatFileNoChecks
五、oat_file_assistant.cc#Dex2Oat 函数分析
在 oat_file_assistant.cc#Dex2Oat 函数中 , 主要是准备 Dex2Oat 可执行二进制程序的相关参数 ,
最终调用了
Exec(argv, error_msg)
函数 , 完成 Dex2Oat 执行的过程 ;
oat_file_assistant.cc#Dex2Oat 函数源码 :
bool OatFileAssistant::Dex2Oat(const std::vector<std::string>& args, std::string* error_msg) { Runtime* runtime = Runtime::Current(); std::string image_location = ImageLocation(); if (image_location.empty()) { *error_msg = "No image location found for Dex2Oat."; return false; } std::vector<std::string> argv; argv.push_back(runtime->GetCompilerExecutable()); argv.push_back("--runtime-arg"); argv.push_back("-classpath"); argv.push_back("--runtime-arg"); std::string class_path = runtime->GetClassPathString(); if (class_path == "") { class_path = OatFile::kSpecialSharedLibrary; } argv.push_back(class_path); if (runtime->IsJavaDebuggable()) { argv.push_back("--debuggable"); } runtime->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv); if (!runtime->IsVerificationEnabled()) { argv.push_back("--compiler-filter=verify-none"); } if (runtime->MustRelocateIfPossible()) { argv.push_back("--runtime-arg"); argv.push_back("-Xrelocate"); } else { argv.push_back("--runtime-arg"); argv.push_back("-Xnorelocate"); } if (!kIsTargetBuild) { argv.push_back("--host"); } argv.push_back("--boot-image=" + image_location); std::vector<std::string> compiler_options = runtime->GetCompilerOptions(); argv.insert(argv.end(), compiler_options.begin(), compiler_options.end()); argv.insert(argv.end(), args.begin(), args.end()); std::string command_line(android::base::Join(argv, ' ')); // ★ 核心跳转 return Exec(argv, error_msg); }
源码路径 : /art/runtime/oat_file_assistant.cc#Dex2Oat