Android虚拟机art流程:查看JNI_CreateJavaVM 对运行时 oat文件的加载(4)

  • A+
所属分类:art虚拟机

我们从

startVm————》JNI_CreateJavaVM---》Runtime::Create---》Runtime::Init

 

一路走来的,然后我们看下Init 里面如何建立heap和oat文件的加载。

 

bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
 heap_ = new gc::Heap(runtime_options.GetOrDefault(Opt::MemoryInitialSize),
 .
 .
 }

 

这里新建这个heap。 /art/runtime/gc/heap.cc

Heap::Heap(size_t initial_size,
           size_t growth_limit,
           ....
{
               
uint8_t* const original_requested_alloc_space_begin = requested_alloc_space_begin;
    for (size_t index = 0; index < image_file_names.size(); ++index) {
      std::string& image_name = image_file_names[index];
      std::string error_msg;
      space::ImageSpace* boot_image_space = space::ImageSpace::CreateBootImage(
          image_name.c_str(),
          image_instruction_set,
          index > 0,
          &error_msg);
      if (boot_image_space != nullptr) {
        AddSpace(boot_image_space);
        ...

        if (index == 0) {
...
          const OatFile* boot_oat_file = boot_image_space->GetOatFile();
          if (boot_oat_file == nullptr) {
            continue;
          }

          const OatHeader& boot_oat_header = boot_oat_file->GetOatHeader();
          const char* boot_classpath =
              boot_oat_header.GetStoreValueByKey(OatHeader::kBootClassPathKey);
          if (boot_classpath == nullptr) {
            continue;
          }

          space::ImageSpace::CreateMultiImageLocations(image_file_name,
                                                       boot_classpath,
                                                       &image_file_names);
        }
      } else {
....
      }
    }
  }
    
    
}

 

目前我只关注这个

CreateBootImage
ImageSpace* ImageSpace::CreateBootImage(const char* image_location,
                                        const InstructionSet image_isa,
                                        bool secondary_image,
                                        std::string* error_msg) {
  ScopedTrace trace(__FUNCTION__);
  std::string system_filename;
  bool has_system = false;
  std::string cache_filename;
  bool has_cache = false;
  bool dalvik_cache_exists = false;
  bool is_global_cache = true;
  bool found_image = FindImageFilename(image_location, image_isa, &system_filename,
                                       &has_system, &cache_filename, &dalvik_cache_exists,
                                       &has_cache, &is_global_cache);

 

先找到 boot.art 文件。怎么找可以看这个函数具体的。

ImageSpace* space;
       space = ImageSpace::Init(image_filename->c_str(),
                               image_location,
                               !(is_system || relocated_version_used),
                               /* oat_file */nullptr,
                               error_msg);

 

ImageSpace* ImageSpace::Init(const char* image_filename,
                             const char* image_location,{
                                 
ImageHeader temp_image_header;
  ImageHeader* image_header = &temp_image_header;
  {
    TimingLogger::ScopedTiming timing("ReadImageHeader", &logger);
    bool success = file->ReadFully(image_header, sizeof(*image_header));
    if (!success || !image_header->IsValid()) {
      *error_msg = StringPrintf("Invalid image header in '%s'", image_filename);
      return nullptr;
    }
  }

 

这个Init 里面先拿到这个boot.art文件的头。里面标记了oat的起止地址和oatdata段和oatexe。就是数据段的执行代码的位置。

std::unique_ptr<ImageSpace> space(new ImageSpace(image_filename,
                                                   image_location,
                                                   map.release(),
                                                   bitmap.release(),
                                                   image_end));


  if (oat_file == nullptr) {
    TimingLogger::ScopedTiming timing("OpenOatFile", &logger);
    space->oat_file_.reset(space->OpenOatFile(image_filename, error_msg));

 

然后 新建一个ImageSpace 然后 OpenOatFile。

OatFile* ImageSpace::OpenOatFile(const char* image_path, std::string* error_msg) const {
  const ImageHeader& image_header = GetImageHeader();
  std::string oat_filename = ImageHeader::GetOatLocationFromImageLocation(image_path);

  CHECK(image_header.GetOatDataBegin() != nullptr);

  OatFile* oat_file = OatFile::Open(oat_filename,
                                    oat_filename,
                                    image_header.GetOatDataBegin(),
                                    image_header.GetOatFileBegin(),
....
                                    error_msg);
 ...
...

  return oat_file;
}

 

这里就会用到我们刚才的image_header的信息。

OatFile* OatFile::Open(const std::string& filename,
                       const std::string& location,
                       uint8_t* requested_base,
                       uint8_t* oat_file_begin,
                       bool executable,
                       bool low_4gb,
                       const char* abs_dex_location,
                       std::string* error_msg) {
  ...
  OatFile* with_dlopen = OatFileBase::OpenOatFile<DlOpenOatFile>(filename,
                                                                location,
                                                                 requested_base,
                                                                 oat_file_begin,
                                                                 
     .....
  if (with_dlopen != nullptr) {
    return with_dlopen;
  }

 

这里的OpenOatFile<DlOpenOatFile> 是个模版,有点绕。

template <typename kOatFileBaseSubType>
OatFileBase* OatFileBase::OpenOatFile(const std::string& elf_filename,
                                      const std::string& location,
                                      uint8_t* requested_base,
                                      uint8_t* oat_file_begin,
                                      bool writable,
                                      bool executable,
                                      bool low_4gb,
                                      const char* abs_dex_location,
                                      std::string* error_msg) {
  std::unique_ptr<OatFileBase> ret(new kOatFileBaseSubType(location, executable));

  

  if (!ret->Load(elf_filename,
                 oat_file_begin,
                 writable,
                 executable,
                 low_4gb,
                 error_msg)) {
    return nullptr;
  }


  return ret.release();
}
bool DlOpenOatFile::Load(const std::string& elf_filename,
                         uint8_t* oat_file_begin,
    ....

  bool success = Dlopen(elf_filename, oat_file_begin, error_msg);
  DCHECK(dlopen_handle_ != nullptr || !success);

  return success;
}
bool DlOpenOatFile::Dlopen(const std::string& elf_filename,
                           uint8_t* oat_file_begin,}
      
    if (oat_file_begin != nullptr) {                            //
      extinfo.flags |= ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS;     // Use the requested addr if
      extinfo.reserved_addr = oat_file_begin;                   // vaddr = 0.
    }                                                           //   (pic boot image).
    dlopen_handle_ = android_dlopen_ext(absolute_path.get(), RTLD_NOW, &extinfo);

}

 

最终它加载的位置在oatdatabegin的位置。 整个就加载完成。

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: