diff options
author | 2023-06-15 15:48:20 +0100 | |
---|---|---|
committer | 2023-07-03 10:52:06 +0000 | |
commit | fdfa590b7b43ca70e497f1a8afe9a641b57ece56 (patch) | |
tree | 6054b4e9ae772c2f135fedde6be62864206ddcad /runtime/class_loader_context.cc | |
parent | 2f8499ef214f9eadb75b36eab43214842f4da64b (diff) |
Reduce multidex checksum to single scalar value.
Change GetMultiDexChecksums to return a single value rather than
a vector. The single checksum represents the whole multidex set,
and will change if any dex file within the multidex set changes.
Fundamentally, we need a value to represent a .zip/.jar archive,
so that we can check whether our build artifacts are up to date.
We previously used a vector of CRC32 values (one per dex file),
however, one combined checksum per archive is also sufficient.
This is necessary, since the future multidex format will have
single zip entry, so we need to adjust the code to expect just
one checksum per zip file. This separates the change to own CL.
The two sides of the checksum comparison are trivially reduced:
* Zip files are reduced by XORing the individual CRC values.
* Likewise, checksums of already open DexFiles are XORed.
As a consequence, ClassLoader path needs to be reduced to
print only single checksum per jar file as well.
Bug: 266950186
Test: ./art/test.py -b --host
Change-Id: I848aee1e4836e87945a5172c7594e266739451e9
Diffstat (limited to 'runtime/class_loader_context.cc')
-rw-r--r-- | runtime/class_loader_context.cc | 53 |
1 files changed, 29 insertions, 24 deletions
diff --git a/runtime/class_loader_context.cc b/runtime/class_loader_context.cc index 2f34f04f5b..1b14449684 100644 --- a/runtime/class_loader_context.cc +++ b/runtime/class_loader_context.cc @@ -17,6 +17,7 @@ #include "class_loader_context.h" #include <algorithm> +#include <optional> #include "android-base/file.h" #include "android-base/parseint.h" @@ -473,14 +474,12 @@ bool ClassLoaderContext::OpenDexFiles(const std::string& classpath_dir, } std::string error_msg; + ArtDexFileLoader dex_file_loader(fd, location); + std::optional<uint32_t> dex_checksum; if (only_read_checksums) { bool zip_file_only_contains_uncompress_dex; - if (!ArtDexFileLoader::GetMultiDexChecksums(location.c_str(), - &dex_checksums, - &dex_locations, - &error_msg, - fd, - &zip_file_only_contains_uncompress_dex)) { + if (!dex_file_loader.GetMultiDexChecksum( + &dex_checksum, &error_msg, &zip_file_only_contains_uncompress_dex)) { LOG(WARNING) << "Could not get dex checksums for location " << location << ", fd=" << fd; dex_files_state_ = kDexFilesOpenFailed; } @@ -489,8 +488,7 @@ bool ClassLoaderContext::OpenDexFiles(const std::string& classpath_dir, // contents. So pass true to verify_checksum. // We don't need to do structural dex file verification, we only need to // check the checksum, so pass false to verify. - size_t opened_dex_files_index = info->opened_dex_files.size(); - ArtDexFileLoader dex_file_loader(location.c_str(), fd, location); + size_t i = info->opened_dex_files.size(); if (!dex_file_loader.Open(/*verify=*/false, /*verify_checksum=*/true, &error_msg, @@ -498,13 +496,14 @@ bool ClassLoaderContext::OpenDexFiles(const std::string& classpath_dir, LOG(WARNING) << "Could not open dex files for location " << location << ", fd=" << fd; dex_files_state_ = kDexFilesOpenFailed; } else { - for (size_t k = opened_dex_files_index; k < info->opened_dex_files.size(); k++) { - std::unique_ptr<const DexFile>& dex = info->opened_dex_files[k]; - dex_locations.push_back(dex->GetLocation()); - dex_checksums.push_back(dex->GetLocationChecksum()); - } + dex_checksum = DexFileLoader::GetMultiDexChecksum(info->opened_dex_files, &i); + DCHECK_EQ(i, info->opened_dex_files.size()); } } + if (dex_checksum.has_value()) { + dex_locations.push_back(location); + dex_checksums.push_back(dex_checksum.value()); + } } // We finished opening the dex files from the classpath. @@ -518,8 +517,8 @@ bool ClassLoaderContext::OpenDexFiles(const std::string& classpath_dir, // Note that this will also remove the paths that could not be opened. info->original_classpath = std::move(info->classpath); DCHECK(dex_locations.size() == dex_checksums.size()); - info->classpath = dex_locations; - info->checksums = dex_checksums; + info->classpath = std::move(dex_locations); + info->checksums = std::move(dex_checksums); AddToWorkList(info, work_list); } @@ -692,16 +691,16 @@ void ClassLoaderContext::EncodeContextInternal(const ClassLoaderInfo& info, } } - for (size_t k = 0; k < info.opened_dex_files.size(); k++) { + for (size_t k = 0; k < info.opened_dex_files.size();) { const std::unique_ptr<const DexFile>& dex_file = info.opened_dex_files[k]; + uint32_t checksum = DexFileLoader::GetMultiDexChecksum(info.opened_dex_files, &k); + if (for_dex2oat) { // dex2oat only needs the base location. It cannot accept multidex locations. // So ensure we only add each file once. bool new_insert = seen_locations.insert(DexFileLoader::GetBaseLocation(dex_file->GetLocation())).second; - if (!new_insert) { - continue; - } + CHECK(new_insert); } std::string location = dex_file->GetLocation(); @@ -716,7 +715,7 @@ void ClassLoaderContext::EncodeContextInternal(const ClassLoaderInfo& info, // dex2oat does not need the checksums. if (!for_dex2oat) { - checksums.push_back(dex_file->GetLocationChecksum()); + checksums.push_back(checksum); } } EncodeClassPath(base_dir, locations, checksums, info.type, out); @@ -1155,13 +1154,17 @@ bool ClassLoaderContext::CreateInfoFromClassLoader( } // Now that `info` is in the chain, populate dex files. - for (const DexFile* dex_file : dex_files_loaded) { + for (size_t i = 0; i < dex_files_loaded.size();) { + const DexFile* dex_file = dex_files_loaded[i]; + uint32_t checksum = DexFileLoader::GetMultiDexChecksum(dex_files_loaded, &i); // Dex location of dex files loaded with InMemoryDexClassLoader is always bogus. // Use a magic value for the classpath instead. info->classpath.push_back((type == kInMemoryDexClassLoader) ? kInMemoryDexClassLoaderDexLocationMagic : dex_file->GetLocation()); - info->checksums.push_back(dex_file->GetLocationChecksum()); + info->checksums.push_back(checksum); + } + for (auto* dex_file : dex_files_loaded) { info->opened_dex_files.emplace_back(dex_file); } @@ -1477,8 +1480,10 @@ std::set<const DexFile*> ClassLoaderContext::CheckForDuplicateDexFiles( // in the Android world) - and as such we decide not to warn on them. ClassLoaderInfo* info = class_loader_chain_.get(); for (size_t k = 0; k < info->classpath.size(); k++) { - for (const DexFile* dex_file : dex_files_to_check) { - if (info->checksums[k] == dex_file->GetLocationChecksum() && + for (size_t i = 0; i < dex_files_to_check.size();) { + const DexFile* dex_file = dex_files_to_check[i]; + uint32_t checksum = DexFileLoader::GetMultiDexChecksum(dex_files_to_check, &i); + if (info->checksums[k] == checksum && AreDexNameMatching(info->classpath[k], dex_file->GetLocation())) { result.insert(dex_file); } |