我们从
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 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(filename,
location,
requested_base,
oat_file_begin,
.....
if (with_dlopen != nullptr) {
return with_dlopen;
}
这里的OpenOatFile 是个模版,有点绕。
template
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 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的位置。 整个就加载完成。