- 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的位置。 整个就加载完成。
您可以选择一种方式赞助本站
支付宝扫一扫赞助
微信钱包扫描赞助
赏