/art/dex2oat/dex2oat.cc#Setup 函数源码 :
// 设置编译环境。包括启动运行时和加载/打开引导类路径。 dex2oat::ReturnCode Setup() { TimingLogger::ScopedTiming t("dex2oat Setup", timings_); if (!PrepareImageClasses() || !PrepareCompiledClasses() || !PrepareCompiledMethods()) { return dex2oat::ReturnCode::kOther; } verification_results_.reset(new VerificationResults(compiler_options_.get())); callbacks_.reset(new QuickCompilerCallbacks( verification_results_.get(), IsBootImage() ? CompilerCallbacks::CallbackMode::kCompileBootImage : CompilerCallbacks::CallbackMode::kCompileApp)); RuntimeArgumentMap runtime_options; if (!PrepareRuntimeOptions(&runtime_options)) { return dex2oat::ReturnCode::kOther; } CreateOatWriters(); if (!AddDexFileSources()) { return dex2oat::ReturnCode::kOther; } if (IsBootImage() && image_filenames_.size() > 1) { // 如果我们正在编译引导映像,请将引导类路径存储到键值存储中。 // 我们需要这个多图像的情况。 key_value_store_->Put(OatHeader::kBootClassPathKey, gc::space::ImageSpace::GetMultiImageBootClassPath(dex_locations_, oat_filenames_, image_filenames_)); } if (!IsBootImage()) { // 编译应用程序时,尽早创建运行时以检索oat头所需的映像位置键。 if (!CreateRuntime(std::move(runtime_options))) { return dex2oat::ReturnCode::kCreateRuntime; } if (CompilerFilter::DependsOnImageChecksum(compiler_options_->GetCompilerFilter())) { TimingLogger::ScopedTiming t3("Loading image checksum", timings_); std::vector<gc::space::ImageSpace*> image_spaces = Runtime::Current()->GetHeap()->GetBootImageSpaces(); image_file_location_oat_checksum_ = image_spaces[0]->GetImageHeader().GetOatChecksum(); image_file_location_oat_data_begin_ = reinterpret_cast<uintptr_t>(image_spaces[0]->GetImageHeader().GetOatDataBegin()); image_patch_delta_ = image_spaces[0]->GetImageHeader().GetPatchDelta(); // Store the boot image filename(s). std::vector<std::string> image_filenames; for (const gc::space::ImageSpace* image_space : image_spaces) { image_filenames.push_back(image_space->GetImageFilename()); } std::string image_file_location = android::base::Join(image_filenames, ':'); if (!image_file_location.empty()) { key_value_store_->Put(OatHeader::kImageLocationKey, image_file_location); } } else { image_file_location_oat_checksum_ = 0u; image_file_location_oat_data_begin_ = 0u; image_patch_delta_ = 0; } // Open dex files for class path. std::vector<std::string> class_path_locations = GetClassPathLocations(runtime_->GetClassPathString()); OpenClassPathFiles(class_path_locations, &class_path_files_, &opened_oat_files_, runtime_->GetInstructionSet(), classpath_dir_); // Store the classpath we have right now. std::vector<const DexFile*> class_path_files = MakeNonOwningPointerVector(class_path_files_); std::string encoded_class_path; if (class_path_locations.size() == 1 && class_path_locations[0] == OatFile::kSpecialSharedLibrary) { // When passing the special shared library as the classpath, it is the only path. encoded_class_path = OatFile::kSpecialSharedLibrary; } else { encoded_class_path = OatFile::EncodeDexFileDependencies(class_path_files, classpath_dir_); } key_value_store_->Put(OatHeader::kClassPathKey, encoded_class_path); } // 现在我们已经完成了key\u value\u store\u,开始编写oat文件。 { TimingLogger::ScopedTiming t_dex("Writing and opening dex files", timings_); rodata_.reserve(oat_writers_.size()); for (size_t i = 0, size = oat_writers_.size(); i != size; ++i) { rodata_.push_back(elf_writers_[i]->StartRoData()); // 直接将dex文件解压或复制到oat文件。 std::unique_ptr<MemMap> opened_dex_files_map; std::vector<std::unique_ptr<const DexFile>> opened_dex_files; // 无需验证以下各项的dex文件: // 1)Dexlayout,因为它进行了验证。也可能无法通过验证,因为 // 我们不更新dex校验和。 // 2)当我们有一个vdex文件,这意味着它已经被验证。 const bool verify = !DoDexLayoutOptimizations() && (input_vdex_file_ == nullptr); if (!oat_writers_[i]->WriteAndOpenDexFiles( kIsVdexEnabled ? vdex_files_[i].get() : oat_files_[i].get(), rodata_.back(), instruction_set_, instruction_set_features_.get(), key_value_store_.get(), verify, update_input_vdex_, &opened_dex_files_map, &opened_dex_files)) { return dex2oat::ReturnCode::kOther; } dex_files_per_oat_file_.push_back(MakeNonOwningPointerVector(opened_dex_files)); if (opened_dex_files_map != nullptr) { opened_dex_files_maps_.push_back(std::move(opened_dex_files_map)); for (std::unique_ptr<const DexFile>& dex_file : opened_dex_files) { dex_file_oat_index_map_.emplace(dex_file.get(), i); opened_dex_files_.push_back(std::move(dex_file)); } } else { DCHECK(opened_dex_files.empty()); } } } dex_files_ = MakeNonOwningPointerVector(opened_dex_files_); // 我们不得不将互换决定推迟到现在,因为这是我们真正需要的时候 // 了解我们将要使用的dex文件。 // 确保我们还没有创建驱动程序。 CHECK(driver_ == nullptr); // 如果我们使用交换文件,请确保我们高于阈值以使其成为必要。 if (swap_fd_ != -1) { if (!UseSwap(IsBootImage(), dex_files_)) { close(swap_fd_); swap_fd_ = -1; VLOG(compiler) << "Decided to run without swap."; } else { LOG(INFO) << "Large app, accepted running with swap."; } } // 请注意,dex2oat不会关闭 swap_fd_。编译器驱动程序的交换空间可以做到这一点。 // 如果由于大小原因需要降级编译器筛选器,请立即执行该检查。 if (!IsBootImage() && IsVeryLarge(dex_files_)) { if (!CompilerFilter::IsAsGoodAs(CompilerFilter::kExtract, compiler_options_->GetCompilerFilter())) { LOG(INFO) << "Very large app, downgrading to extract."; // 注意:这个更改不会反映在键值存储中,这是必须的 // 在加载dex文件之前完成。当前需要此设置 // 从DexFile对象获取大小。 // TODO:重构。b/29790079 compiler_options_->SetCompilerFilter(CompilerFilter::kExtract); } } if (IsBootImage()) { // 对于启动映像,将打开的dex文件传递给运行时::Create()。 // 注意:运行时获得这些dex文件的所有权。 runtime_options.Set(RuntimeArgumentMap::BootClassPathDexList, &opened_dex_files_); if (!CreateRuntime(std::move(runtime_options))) { return dex2oat::ReturnCode::kOther; } } // 如果我们正在处理映像,请重写编译器过滤器以强制进行完整编译。必须是 // 在导致验证的WellKnownClasses::Init之前完成。注意:不强制 // 类初始值设定项的编译。 // 当我们在本机中时,请抓住机会初始化众所周知的类。 Thread* self = Thread::Current(); WellKnownClasses::Init(self->GetJniEnv()); ClassLinker* const class_linker = Runtime::Current()->GetClassLinker(); if (!IsBootImage()) { constexpr bool kSaveDexInput = false; if (kSaveDexInput) { SaveDexInput(); } // 句柄和类加载器的创建需要在Runtime::Create之后进行。 ScopedObjectAccess soa(self); // 类路径:首先是给定的类路径。 std::vector<const DexFile*> class_path_files = MakeNonOwningPointerVector(class_path_files_); // 然后我们将编译dex文件。因此,我们将首先解析类路径。 class_path_files.insert(class_path_files.end(), dex_files_.begin(), dex_files_.end()); class_loader_ = class_linker->CreatePathClassLoader(self, class_path_files); } // 确保打开的dex文件对于dex到dex转换是可写的。 for (const std::unique_ptr<MemMap>& map : opened_dex_files_maps_) { if (!map->Protect(PROT_READ | PROT_WRITE)) { PLOG(ERROR) << "Failed to make .dex files writeable."; return dex2oat::ReturnCode::kOther; } } // 确保dex缓存保持活动状态,因为我们不希望在编译期间发生类卸载。 for (const auto& dex_file : dex_files_) { ScopedObjectAccess soa(self); dex_caches_.push_back(soa.AddLocalReference<jobject>( class_linker->RegisterDexFile(*dex_file, soa.Decode<mirror::ClassLoader>(class_loader_).Ptr()))); if (dex_caches_.back() == nullptr) { soa.Self()->AssertPendingException(); soa.Self()->ClearException(); PLOG(ERROR) << "Failed to register dex file."; return dex2oat::ReturnCode::kOther; } // 预注册dex文件,以便在编译和验证期间无需锁定即可访问验证结果。 verification_results_->AddDexFile(dex_file); } return dex2oat::ReturnCode::kNoFailure; }
源码路径 : /art/dex2oat/dex2oat.cc#Setup