Avoid growing boot class path for --single-image compiled images
Calculation of the number of components in Runtime::Init did not
account for images compiled with --single-image where the number of
images does not equal the number of components.
Bug: 160683548
Test: Treehugger
Change-Id: I1db7a4bbbc8bb2f48d54f5048bd1b8407d19cf02
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index f3c58d3..0bed8eb 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1382,6 +1382,11 @@
std::vector<std::unique_ptr<const DexFile>>&& additional_dex_files) {
for (std::unique_ptr<const DexFile>& dex_file : additional_dex_files) {
AppendToBootClassPath(self, dex_file.get());
+ if (kIsDebugBuild) {
+ for (const auto& boot_dex_file : boot_dex_files_) {
+ DCHECK_NE(boot_dex_file->GetLocation(), dex_file->GetLocation());
+ }
+ }
boot_dex_files_.push_back(std::move(dex_file));
}
}
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 0cb9713..a718b5c 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -3534,6 +3534,14 @@
return boot_image_checksum;
}
+size_t ImageSpace::GetNumberOfComponents(ArrayRef<ImageSpace* const> image_spaces) {
+ size_t n = 0;
+ for (auto&& is : image_spaces) {
+ n += is->GetComponentCount();
+ }
+ return n;
+}
+
static size_t CheckAndCountBCPComponents(std::string_view oat_boot_class_path,
ArrayRef<const std::string> boot_class_path,
/*out*/std::string* error_msg) {
diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h
index 36889fe..157c9ac 100644
--- a/runtime/gc/space/image_space.h
+++ b/runtime/gc/space/image_space.h
@@ -189,6 +189,11 @@
return &live_bitmap_;
}
+ // Compute the number of components in the image (contributing jar files).
+ size_t GetComponentCount() const {
+ return GetImageHeader().GetComponentCount();
+ }
+
void Dump(std::ostream& os) const override;
// Sweeping image spaces is a NOP.
@@ -225,6 +230,9 @@
static std::string GetBootClassPathChecksums(ArrayRef<ImageSpace* const> image_spaces,
ArrayRef<const DexFile* const> boot_class_path);
+ // Returns the total number of components (jar files) associated with the image spaces.
+ static size_t GetNumberOfComponents(ArrayRef<gc::space::ImageSpace* const> image_spaces);
+
// Returns whether the checksums are valid for the given boot class path,
// image location and ISA (may differ from the ISA of an initialized Runtime).
// The boot image and dex files do not need to be loaded in memory.
diff --git a/runtime/image.h b/runtime/image.h
index 61db627..c8e5948 100644
--- a/runtime/image.h
+++ b/runtime/image.h
@@ -437,10 +437,12 @@
// their oat files are mmapped independently.
uint32_t image_reservation_size_ = 0u;
- // The number of components.
+ // The number of components (jar files contributing to the image).
// For boot image or boot image extension, the primary image stores the total number
- // of images, secondary images have this set to 0.
- // App images have 1 component.
+ // of components, secondary images have this set to 0. App images have 1 component.
+ // The component count usually matches the total number of images (one image per component), but
+ // if multiple components are compiled with --single-image there will only be 1 image associated
+ // with those components.
uint32_t component_count_ = 0u;
// Required base address for mapping the image.
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index ac3c392..2012a04 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1594,10 +1594,13 @@
GetInternTable()->AddImageStringsToTable(image_space, VoidFunctor());
}
}
- if (heap_->GetBootImageSpaces().size() != GetBootClassPath().size()) {
+
+ const size_t total_components = gc::space::ImageSpace::GetNumberOfComponents(
+ ArrayRef<gc::space::ImageSpace* const>(heap_->GetBootImageSpaces()));
+ if (total_components != GetBootClassPath().size()) {
// The boot image did not contain all boot class path components. Load the rest.
- DCHECK_LT(heap_->GetBootImageSpaces().size(), GetBootClassPath().size());
- size_t start = heap_->GetBootImageSpaces().size();
+ CHECK_LT(total_components, GetBootClassPath().size());
+ size_t start = total_components;
DCHECK_LT(start, GetBootClassPath().size());
std::vector<std::unique_ptr<const DexFile>> extra_boot_class_path;
if (runtime_options.Exists(Opt::BootClassPathDexList)) {