当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()函数来完成编译过程。

更多相关文章

  1. 关于android的设备管理器-DevicePolicyManager(二)
  2. Android(安卓)ButterKnife导入使用出错解决
  3. Android(安卓)Gradle 学习之二:重命名APK
  4. Android学习备忘021——FBReader源码修改package name
  5. React Native获取移动设备信息(react-native-device-info)如何使
  6. android在线预览office
  7. Android(安卓)开发最佳实践--转自Git
  8. 【Android(安卓)OTA】用nodejs搭建服务器
  9. Android(安卓)AWS S3文件服务器User Pool Identity Pool接入

随机推荐

  1. 4.2以上版本的sdk使用webview js和java代
  2. 关于Android中使用Handler造成内存泄露的
  3. android相机如何只显示处理后的图像以及
  4. Android选择图片
  5. 超酷的计步器APP(一)——炫酷功能实现,自定
  6. Android(安卓)中的危险权限详细整理
  7. Android(安卓)版本更新签名冲突的问题以
  8. 谁能想到,Android外包工作三年,能入职某大
  9. Android应用《撕开美女衣服》的实现过程
  10. 国产神器天语Android双核手机W700线下赏