Dex2Oat源码流程(1)——Android6.0

来源:互联网 发布:英翻汉软件 编辑:程序博客网 时间:2024/06/11 19:34

当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()函数中,

  1. arm上的workaround由b13564922()完成,这个与dex2oat的主要线程无关,可以暂时忽略。
  2. 构造Dex2oat对象——Dex2Oat dex2oat(&timings);
  3. 处理命令行参数,将dex文件名文件路径等参数传入函数中——dex2oat.ParseArgs(argc, argv);
  4. 判断对于dex文件是否有写的权限——dex2oat.OpenFile()
  5. 打印命令行参数——LOG(INFO) << CommandLine();
  6. 判断dex2oat编译环境是否启动成功——dex2oat.Setup()
  7. 根据是否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()函数来完成编译过程。

阅读全文
0 0
原创粉丝点击