//路径:/art/runtime/dex_file.cc boolDexFile::OpenAllDexFilesFromZip(const ZipArchive& zip_archive, const std::string& location, bool verify_checksum, std::string* error_msg, std::vector<std::unique_ptr<const DexFile>>* dex_files){ ScopedTrace trace("Dex file open from Zip " + std::string(location)); DCHECK(dex_files != nullptr) << "DexFile::OpenFromZip: out-param is nullptr"; ZipOpenErrorCode error_code; //调用OpenOneDexFileFromZip()从zip文件中打开dex文件 std::unique_ptr<const DexFile> dex_file(OpenOneDexFileFromZip(zip_archive, kClassesDex, location, verify_checksum, error_msg, &error_code)); if (dex_file.get() == nullptr) { returnfalse; } else { dex_files->push_back(std::move(dex_file)); //zip文件中存在多个dex文件 for (size_t i = 1; ; ++i) { std::string name = GetMultiDexClassesDexName(i); std::string fake_location = GetMultiDexLocation(i, location.c_str()); //调用OpenOneDexFileFromZip() std::unique_ptr<const DexFile> next_dex_file(OpenOneDexFileFromZip(zip_archive, name.c_str(), fake_location, verify_checksum, error_msg, &error_code)); if (next_dex_file.get() == nullptr) { if (error_code != ZipOpenErrorCode::kEntryNotFound) { LOG(WARNING) << "Zip open failed: " << *error_msg; } break; } else { dex_files->push_back(std::move(next_dex_file)); }
if (i == kWarnOnManyDexFilesThreshold) { LOG(WARNING) << location << " has in excess of " << kWarnOnManyDexFilesThreshold << " dex files. Please consider coalescing and shrinking the number to " " avoid runtime overhead."; }
if (i == std::numeric_limits<size_t>::max()) { LOG(ERROR) << "Overflow in number of dex files!"; break; } }
//路径:/art/runtime/dex_file.cc std::unique_ptr<const DexFile> DexFile::OpenOneDexFileFromZip(const ZipArchive& zip_archive, constchar* entry_name, const std::string& location, bool verify_checksum, std::string* error_msg, ZipOpenErrorCode* error_code){ ScopedTrace trace("Dex file open from Zip Archive " + std::string(location)); CHECK(!location.empty());
//调用zip_archive.Find()找到给定的dex文件 std::unique_ptr<ZipEntry> zip_entry(zip_archive.Find(entry_name, error_msg)); if (zip_entry == nullptr) { *error_code = ZipOpenErrorCode::kEntryNotFound; returnnullptr; } if (zip_entry->GetUncompressedLength() == 0) { *error_msg = StringPrintf("Dex file '%s' has zero length", location.c_str()); *error_code = ZipOpenErrorCode::kDexFileError; returnnullptr; }
std::unique_ptr<MemMap> map; if (zip_entry->IsUncompressed()) { //是否文件对齐 if (!zip_entry->IsAlignedTo(alignof(Header))) { ...... } else { // dex文件解压缩? map.reset(zip_entry->MapDirectlyFromFile(location.c_str(), /*out*/error_msg)); if (map == nullptr) { LOG(WARNING) << "Can't mmap dex file " << location << "!" << entry_name << " directly; " << "is your ZIP file corrupted? Falling back to extraction."; // Try again with Extraction which still has a chance of recovery. } } }
if (map == nullptr) { // Default path for compressed ZIP entries, // and fallback for stored ZIP entries. map.reset(zip_entry->ExtractToMemMap(location.c_str(), entry_name, error_msg)); }
if (map->Size() < sizeof(DexFile::Header)) { *error_msg = StringPrintf( "DexFile: failed to open dex file '%s' that is too short to have a header", location.c_str()); returnnullptr; }
CHECK(begin_ != nullptr) << GetLocation(); CHECK_GT(size_, 0U) << GetLocation(); // Check base (=header) alignment. // Must be 4-byte aligned to avoid undefined behavior when accessing // any of the sections via a pointer. CHECK_ALIGNED(begin_, alignof(Header));
voidDexFile::InitializeSectionsFromMapList(){ const MapList* map_list = reinterpret_cast<const MapList*>(begin_ + header_->map_off_); if (header_->map_off_ == 0 || header_->map_off_ > size_) { // Bad offset. The dex file verifier runs after this method and will reject the file. return; } constsize_t count = map_list->size_;
size_t map_limit = header_->map_off_ + count * sizeof(MapItem); if (header_->map_off_ >= map_limit || map_limit > size_) { // Overflow or out out of bounds. The dex file verifier runs after // this method and will reject the file as it is malformed. return; }