当framework层的PackageManagerService需要执行安装请求时,需要对目标APK文件进行处理,而这个过程归根到底是对dex文件的处理,Android将dex文件转化为虚拟机可以直接执行的oat文件,这个转化过程是在art/dex2oat/dex2oat.cc(http://androidxref.com/6.0.0_r1/xref/art/dex2oat/dex2oat.cc)中完成的。
从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;
}
main函数中,调用了art命名空间下的dex2oat函数,在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
这两个函数可以一起分析,从他们的代码中可以看出,代码基本上一样。
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()函数。
在这一步,创建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()函数来完成编译过程。