// Class that is used to open dex files and deal with corresponding multidex and location logic. class DexFileLoader { public: // name of the DexFile entry within a zip archive static constexpr constchar* kClassesDex = "classes.dex";
// The separator character in MultiDex locations. static constexpr char kMultiDexSeparator = '!';
// Return true if the magic is valid for dex or cdex. staticbool IsMagicValid(uint32_t magic); staticbool IsMagicValid(const uint8_t* magic);
// Return true if the corresponding version and magic is valid. staticbool IsVersionAndMagicValid(const uint8_t* magic);
// Check whether a location denotes a multidex dex file. This is a very simple check: returns // whether the string contains the separator character. staticbool IsMultiDexLocation(std::string_view location);
// Return the name of the index-th classes.dex in a multidex zip file. This is classes.dex for // index == 0, and classes{index + 1}.dex otherwise (i.e. classes.dex, classes2.dex, etc...). static std::string GetMultiDexZipEntryName(size_t index);
// Return the (possibly synthetic) dex location for a multidex entry. This is dex_location for // index == 0, and dex_location + multi-dex-separator + GetMultiDexZipEntryName(index) else. static std::string GetMultiDexLocation(constchar* dex_location, size_t index);
// Returns the multidex location and the checksum for each dex file in a zip or a dex container. // // This uses the source path provided to DexFileLoader constructor. // // Returns false on error. bool GetMultiDexChecksums(/*out*/ std::vector<uint32_t>* checksums, /*out*/ std::string* error_msg, /*out*/ bool* only_contains_uncompressed_dex = nullptr);
// Returns combined checksum of one or more dex files (one checksum for the whole multidex set). // // This uses the source path provided to DexFileLoader constructor. // // Returns false on error. Sets *checksum to nullopt for an empty set. bool GetMultiDexChecksum(/*out*/ std::optional<uint32_t>* checksum, /*out*/ std::string* error_msg, /*out*/ bool* only_contains_uncompressed_dex = nullptr);
// Returns combined checksum of one or more dex files (one checksum for the whole multidex set). // // This uses already open dex files. // // It starts iteration at index 'i', which must be a primary dex file, // and it sets 'i' to the next primary dex file or to end of the array. template <typename DexFilePtrVector> // array|vector<unique_ptr|DexFile|OatDexFile*>. static uint32_t GetMultiDexChecksum(const DexFilePtrVector& dex_files, /*inout*/ size_t* i) {
CHECK_LT(*i, dex_files.size()) << "No dex files";
std::optional<uint32_t> checksum; for (; *i < dex_files.size(); ++(*i)) { constauto* dex_file = &*dex_files[*i]; bool is_primary_dex = !IsMultiDexLocation(dex_file->GetLocation()); if (!checksum.has_value()) { // First dex file.
CHECK(is_primary_dex) << dex_file->GetLocation(); // Expect primary dex.
} elseif (is_primary_dex) { // Later dex file. break; // Found another primary dex file, terminate iteration.
} if (!is_primary_dex && dex_file->GetDexVersion() >= DexFile::kDexContainerVersion) { if (dex_file->GetLocationChecksum() == dex_files[*i - 1]->GetLocationChecksum()) { continue;
}
}
checksum = checksum.value_or(kEmptyMultiDexChecksum) ^ dex_file->GetLocationChecksum();
}
CHECK(checksum.has_value()); return checksum.value();
}
// Calculate checksum of dex files in a vector, starting at index 0. // It will CHECK that the whole vector is consumed (i.e. there is just one primary dex file). template <typename DexFilePtrVector> static uint32_t GetMultiDexChecksum(const DexFilePtrVector& dex_files) {
size_t i = 0;
uint32_t checksum = GetMultiDexChecksum(dex_files, &i);
CHECK_EQ(i, dex_files.size()); return checksum;
}
// Non-zero initial value for multi-dex to catch bugs if multi-dex checksum is compared // directly to DexFile::GetLocationChecksum without going through GetMultiDexChecksum. static constexpr uint32_t kEmptyMultiDexChecksum = 1;
// Returns the canonical form of the given dex location. // // There are different flavors of "dex locations" as follows: // the file name of a dex file: // The actual file path that the dex file has on disk. // dex_location: // This acts as a key for the class linker to know which dex file to load. // It may correspond to either an old odex file or a particular dex file // inside an oat file. In the first case it will also match the file name // of the dex file. In the second case (oat) it will include the file name // and possibly some multidex annotation to uniquely identify it. // canonical_dex_location: // the dex_location where its file name part has been made canonical. static std::string GetDexCanonicalLocation(constchar* dex_location);
// Split the dex location into the base location (filename) and the multidex index. // The index is 0-based. static std::pair<std::string_view, size_t> SplitMultiDexLocation(std::string_view location);
// For normal dex files, location and base location coincide. If a dex file is part of a multidex // archive, the base location is the name of the originating jar/apk, stripped of any internal // classes*.dex path. static std::string GetBaseLocation(std::string_view location) { return std::string(SplitMultiDexLocation(location).first);
}
DexFileLoader(constchar* filename, const File* file, const std::string& location)
: filename_(filename), file_(file), location_(location) {
CHECK(file != nullptr); // Must be non-null, but may be invalid.
}
// This constructor uses the same path to both load the file and set the dex // location, and hence it must not be used in dex2oat where they may be // different (cf. DexFile.location_ comment). explicit DexFileLoader(const std::string& location)
: DexFileLoader(location.c_str(), /*file=*/&kInvalidFile, location) {}
virtual ~DexFileLoader() {}
// Open singe dex file at the given offset within the container (usually 0). // This intentionally ignores all other dex files in the container
std::unique_ptr<const DexFile> OpenOne(size_t header_offset,
uint32_t location_checksum, const OatDexFile* oat_dex_file, bool verify, bool verify_checksum,
std::string* error_msg);
// Open single dex file (starting at offset 0 of the container). // It expects only single dex file to be present and will fail otherwise.
std::unique_ptr<const DexFile> Open(uint32_t location_checksum, const OatDexFile* oat_dex_file, bool verify, bool verify_checksum,
std::string* error_msg) {
std::unique_ptr<const DexFile> dex_file = OpenOne( /*header_offset=*/0, location_checksum, oat_dex_file, verify, verify_checksum, error_msg); // This API returns only singe DEX file, so check there is just single dex in the container.
CHECK(dex_file == nullptr || dex_file->IsDexContainerLastEntry()) << location_; return dex_file;
}
// Ensure we have root container. If we are backed by a file, memory-map it. // We can only do this for dex files since zip files might be too big to map. bool MapRootContainer(std::string* error_msg);
// Open .dex files from the entry_name in a zip archive. bool OpenFromZipEntry(const ZipArchive& zip_archive, constchar* entry_name, const std::string& location, bool verify, bool verify_checksum, /*inout*/ size_t* multidex_count, /*out*/ DexFileLoaderErrorCode* error_code, /*out*/ std::string* error_msg, /*out*/ std::vector<std::unique_ptr<const DexFile>>* dex_files) const;
// The DexFileLoader can be backed either by file or by memory (i.e. DexFileContainer). // We can not just mmap the file since APKs might be unreasonably large for 32-bit system.
std::string filename_; const File* file_ = &kInvalidFile;
std::optional<File> owned_file_; // May be used as backing storage for 'file_'.
std::shared_ptr<DexFileContainer> root_container_;
// The full absolute path to the dex file, if it was loaded from disk. See // DexFile.location_ for details. const std::string location_;
};
} // namespace art
#endif// ART_LIBDEXFILE_DEX_DEX_FILE_LOADER_H_
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-06-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.