Dex2Oat源码流程(1)——Android6.0
16lz
2021-01-26
当framework层的PackageManagerService需要执行安装请求时,需要对目标APK文件进行处理,而这个过程归根到底是对dex文件的处理,Android将dex文件转化为虚拟机可以直接执行的oat文件,这个转化过程是在art/dex2oat/dex2oat.cc(http://androidxref.com/6.0.0_r1/xref/art/dex2oat/dex2oat.cc)中完成的。
main()
从dex2oat.cc的执行入口main函数开始跟踪,可以很容易看出dex2oat的逻辑:
int main(int argc, char** argv) { int result = art::dex2oat(argc, argv); // Everything was done, do an explicit exit here to avoid running Runtime destructors that take // time (bug 10645725) unless we're a debug build or running on valgrind. Note: The Dex2Oat class // should not destruct the runtime in this case. if (!art::kIsDebugBuild && (RUNNING_ON_VALGRIND == 0)) { exit(result); } return result;}
dex2oat()
main函数中,调用了art命名空间下的dex2oat函数,在dex2oat()函数中,
- arm上的workaround由b13564922()完成,这个与dex2oat的主要线程无关,可以暂时忽略。
- 构造Dex2oat对象——Dex2Oat dex2oat(&timings);
- 处理命令行参数,将dex文件名文件路径等参数传入函数中——dex2oat.ParseArgs(argc, argv);
- 判断对于dex文件是否有写的权限——dex2oat.OpenFile()
- 打印命令行参数——LOG(INFO) << CommandLine();
- 判断dex2oat编译环境是否启动成功——dex2oat.Setup()
- 根据是否image分别调用CompileImage(dex2oat)或CompileApp(dex2oat)的处理
static int dex2oat(int argc, char** argv) { b13564922(); TimingLogger timings("compiler", false, false); Dex2Oat dex2oat(&timings); // Parse arguments. Argument mistakes will lead to exit(EXIT_FAILURE) in UsageError. dex2oat.ParseArgs(argc, argv); // Check early that the result of compilation can be written if (!dex2oat.OpenFile()) { return EXIT_FAILURE; } // Print the complete line when any of the following is true: // 1) Debug build // 2) Compiling an image // 3) Compiling with --host // 4) Compiling on the host (not a target build) // Otherwise, print a stripped command line. if (kIsDebugBuild || dex2oat.IsImage() || dex2oat.IsHost() || !kIsTargetBuild) { LOG(INFO) << CommandLine(); } else { LOG(INFO) << StrippedCommandLine(); } if (!dex2oat.Setup()) { dex2oat.EraseOatFile(); return EXIT_FAILURE; } if (dex2oat.IsImage()) { return CompileImage(dex2oat); } else { return CompileApp(dex2oat); }}} // namespace art
CompileApp()&&CompileImage()
这两个函数可以一起分析,从他们的代码中可以看出,代码基本上一样。
dex2oat.Compile()的代码如下所示:
static int CompileImage(Dex2Oat& dex2oat) { dex2oat.Compile(); // Create the boot.oat. if (!dex2oat.CreateOatFile()) { dex2oat.EraseOatFile(); return EXIT_FAILURE; } // Flush and close the boot.oat. We always expect the output file by name, and it will be // re-opened from the unstripped name. if (!dex2oat.FlushCloseOatFile()) { return EXIT_FAILURE; } // Creates the boot.art and patches the boot.oat. if (!dex2oat.HandleImage()) { return EXIT_FAILURE; } // When given --host, finish early without stripping. if (dex2oat.IsHost()) { dex2oat.DumpTiming(); return EXIT_SUCCESS; } // Copy unstripped to stripped location, if necessary. if (!dex2oat.CopyUnstrippedToStripped()) { return EXIT_FAILURE; } // FlushClose again, as stripping might have re-opened the oat file. if (!dex2oat.FlushCloseOatFile()) { return EXIT_FAILURE; } dex2oat.DumpTiming(); return EXIT_SUCCESS;}
CompileApp()的代码如下所示:
static int CompileApp(Dex2Oat& dex2oat) { dex2oat.Compile(); // Create the app oat. if (!dex2oat.CreateOatFile()) { dex2oat.EraseOatFile(); return EXIT_FAILURE; } // Do not close the oat file here. We might haven gotten the output file by file descriptor, // which we would lose. if (!dex2oat.FlushOatFile()) { return EXIT_FAILURE; } // When given --host, finish early without stripping. if (dex2oat.IsHost()) { if (!dex2oat.FlushCloseOatFile()) { return EXIT_FAILURE; } dex2oat.DumpTiming(); return EXIT_SUCCESS; } // Copy unstripped to stripped location, if necessary. This will implicitly flush & close the // unstripped version. If this is given, we expect to be able to open writable files by name. if (!dex2oat.CopyUnstrippedToStripped()) { return EXIT_FAILURE; } // Flush and close the file. if (!dex2oat.FlushCloseOatFile()) { return EXIT_FAILURE; } dex2oat.DumpTiming(); return EXIT_SUCCESS;}
可以看出他们有一个共同的特点,就是都先调用了dex2oat.Compile()函数。
Compile()
在这一步,创建compiler driver,编译所有的dex文件。dex2oat.Compile()的代码如下所示:
// Create and invoke the compiler driver. This will compile all the dex files. void Compile() { TimingLogger::ScopedTiming t("dex2oat Compile", timings_); compiler_phases_timings_.reset(new CumulativeLogger("compilation times")); // Handle and ClassLoader creation needs to come after Runtime::Create jobject class_loader = nullptr; Thread* self = Thread::Current(); if (!boot_image_option_.empty()) { ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); OpenClassPathFiles(runtime_->GetClassPathString(), dex_files_, &class_path_files_); ScopedObjectAccess soa(self); // Classpath: first the class-path given. std::vector<const DexFile*> class_path_files; for (auto& class_path_file : class_path_files_) { class_path_files.push_back(class_path_file.get()); } // Store the classpath we have right now. key_value_store_->Put(OatHeader::kClassPathKey, OatFile::EncodeDexFileDependencies(class_path_files)); // Then the dex files we'll compile. Thus we'll resolve the class-path first. class_path_files.insert(class_path_files.end(), dex_files_.begin(), dex_files_.end()); class_loader = class_linker->CreatePathClassLoader(self, class_path_files); } driver_.reset(new CompilerDriver(compiler_options_.get(), verification_results_.get(), &method_inliner_map_, compiler_kind_, instruction_set_, instruction_set_features_.get(), image_, image_classes_.release(), compiled_classes_.release(), nullptr, thread_count_, dump_stats_, dump_passes_, dump_cfg_file_name_, compiler_phases_timings_.get(), swap_fd_, profile_file_)); driver_->CompileAll(class_loader, dex_files_, timings_); }
这一步的操作由driver_这个对象完成的,而这个对象在Dex2Oat类中由CompilerDriver 创建的——CompilerDriver* driver_;之后调用driver_的ComileAll()函数来完成编译过程。
更多相关文章
- 关于android的设备管理器-DevicePolicyManager(二)
- Android(安卓)ButterKnife导入使用出错解决
- Android(安卓)Gradle 学习之二:重命名APK
- Android学习备忘021——FBReader源码修改package name
- React Native获取移动设备信息(react-native-device-info)如何使
- android在线预览office
- Android(安卓)开发最佳实践--转自Git
- 【Android(安卓)OTA】用nodejs搭建服务器
- Android(安卓)AWS S3文件服务器User Pool Identity Pool接入