diff options
author | 2018-12-07 17:18:07 +0000 | |
---|---|---|
committer | 2018-12-07 17:23:26 +0000 | |
commit | db4b1deebf425be5f1d0f597d1ef540f19908324 (patch) | |
tree | 5851aab8a4d71b49dbd272b822bfd1ae2cbd08df | |
parent | e3c6dfe2009d2fad6f8e4401cb17935bdd09ab9e (diff) |
Revert "Pass boot class path to ImageSpace::LoadBootImage."
This reverts commit d19085141ad9c71eae1b0ff585999ac8e27dadd4.
Also squash a revert of
Fix oatdump tests on target.
(commit 77eea0898aca2881a87afd177a0422870c39a318)
Reason for revert: Broke JDWP tests.
Bug: 119868597
Change-Id: I005097d2d96014c961e5a4c0b089e7675004febc
-rw-r--r-- | cmdline/cmdline_parser_test.cc | 15 | ||||
-rw-r--r-- | dex2oat/dex2oat.cc | 98 | ||||
-rw-r--r-- | dex2oat/linker/image_test.h | 14 | ||||
-rw-r--r-- | oatdump/oatdump_test.h | 5 | ||||
-rw-r--r-- | runtime/class_linker.cc | 23 | ||||
-rw-r--r-- | runtime/gc/heap.cc | 6 | ||||
-rw-r--r-- | runtime/gc/heap.h | 4 | ||||
-rw-r--r-- | runtime/gc/space/image_space.cc | 246 | ||||
-rw-r--r-- | runtime/gc/space/image_space.h | 19 | ||||
-rw-r--r-- | runtime/interpreter/unstarted_runtime.cc | 11 | ||||
-rw-r--r-- | runtime/jdwp/jdwp_handler.cc | 3 | ||||
-rw-r--r-- | runtime/native/dalvik_system_VMRuntime.cc | 6 | ||||
-rw-r--r-- | runtime/oat.h | 4 | ||||
-rw-r--r-- | runtime/parsed_options.cc | 40 | ||||
-rw-r--r-- | runtime/parsed_options_test.cc | 9 | ||||
-rw-r--r-- | runtime/runtime.cc | 71 | ||||
-rw-r--r-- | runtime/runtime.h | 13 | ||||
-rw-r--r-- | runtime/runtime_options.def | 2 | ||||
-rwxr-xr-x | tools/run-libcore-tests.sh | 16 |
19 files changed, 327 insertions, 278 deletions
diff --git a/cmdline/cmdline_parser_test.cc b/cmdline/cmdline_parser_test.cc index 101e5c42cd..97daafadd8 100644 --- a/cmdline/cmdline_parser_test.cc +++ b/cmdline/cmdline_parser_test.cc @@ -63,12 +63,6 @@ namespace art { return expected == actual; } - template <char Separator> - bool UsuallyEquals(const std::vector<std::string>& expected, - const ParseStringList<Separator>& actual) { - return expected == static_cast<std::vector<std::string>>(actual); - } - // Try to use memcmp to compare simple plain-old-data structs. // // This should *not* generate false positives, but it can generate false negatives. @@ -224,13 +218,8 @@ TEST_F(CmdlineParserTest, TestSimpleSuccesses) { } EXPECT_SINGLE_PARSE_EXISTS("-Xzygote", M::Zygote); - EXPECT_SINGLE_PARSE_VALUE(std::vector<std::string>({"/hello/world"}), - "-Xbootclasspath:/hello/world", - M::BootClassPath); - EXPECT_SINGLE_PARSE_VALUE(std::vector<std::string>({"/hello", "/world"}), - "-Xbootclasspath:/hello:/world", - M::BootClassPath); - EXPECT_SINGLE_PARSE_VALUE_STR("/hello/world", "-classpath /hello/world", M::ClassPath); + EXPECT_SINGLE_PARSE_VALUE_STR("/hello/world", "-Xbootclasspath:/hello/world", M::BootClassPath); + EXPECT_SINGLE_PARSE_VALUE("/hello/world", "-Xbootclasspath:/hello/world", M::BootClassPath); EXPECT_SINGLE_PARSE_VALUE(Memory<1>(234), "-Xss234", M::StackSize); EXPECT_SINGLE_PARSE_VALUE(MemoryKiB(1234*MB), "-Xms1234m", M::MemoryInitialSize); EXPECT_SINGLE_PARSE_VALUE(true, "-XX:EnableHSpaceCompactForOOM", M::EnableHSpaceCompactForOOM); diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index a5bba9bb97..f7299344f2 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -103,7 +103,6 @@ namespace art { using android::base::StringAppendV; using android::base::StringPrintf; -using gc::space::ImageSpace; static constexpr size_t kDefaultMinDexFilesForSwap = 2; static constexpr size_t kDefaultMinDexFileCumulativeSizeForSwap = 20 * MB; @@ -965,24 +964,91 @@ class Dex2Oat final { } void ExpandOatAndImageFilenames() { - if (image_filenames_[0].rfind('/') == std::string::npos) { - Usage("Unusable boot image filename %s", image_filenames_[0].c_str()); + std::string base_oat = oat_filenames_[0]; + size_t last_oat_slash = base_oat.rfind('/'); + if (last_oat_slash == std::string::npos) { + Usage("Unusable boot image oat filename %s", base_oat.c_str()); + } + // We also need to honor path components that were encoded through '@'. Otherwise the loading + // code won't be able to find the images. + if (base_oat.find('@', last_oat_slash) != std::string::npos) { + last_oat_slash = base_oat.rfind('@'); + } + base_oat = base_oat.substr(0, last_oat_slash + 1); + + std::string base_img = image_filenames_[0]; + size_t last_img_slash = base_img.rfind('/'); + if (last_img_slash == std::string::npos) { + Usage("Unusable boot image filename %s", base_img.c_str()); + } + // We also need to honor path components that were encoded through '@'. Otherwise the loading + // code won't be able to find the images. + if (base_img.find('@', last_img_slash) != std::string::npos) { + last_img_slash = base_img.rfind('@'); } - image_filenames_ = ImageSpace::ExpandMultiImageLocations(dex_locations_, image_filenames_[0]); - if (oat_filenames_[0].rfind('/') == std::string::npos) { - Usage("Unusable boot image oat filename %s", oat_filenames_[0].c_str()); + // Get the prefix, which is the primary image name (without path components). Strip the + // extension. + std::string prefix = base_img.substr(last_img_slash + 1); + if (prefix.rfind('.') != std::string::npos) { + prefix = prefix.substr(0, prefix.rfind('.')); } - oat_filenames_ = ImageSpace::ExpandMultiImageLocations(dex_locations_, oat_filenames_[0]); + if (!prefix.empty()) { + prefix = prefix + "-"; + } + + base_img = base_img.substr(0, last_img_slash + 1); + std::string base_symbol_oat; if (!oat_unstripped_.empty()) { - if (oat_unstripped_[0].rfind('/') == std::string::npos) { - Usage("Unusable boot image symbol filename %s", oat_unstripped_[0].c_str()); + base_symbol_oat = oat_unstripped_[0]; + size_t last_symbol_oat_slash = base_symbol_oat.rfind('/'); + if (last_symbol_oat_slash == std::string::npos) { + Usage("Unusable boot image symbol filename %s", base_symbol_oat.c_str()); + } + base_symbol_oat = base_symbol_oat.substr(0, last_symbol_oat_slash + 1); + } + + // Now create the other names. Use a counted loop to skip the first one. + for (size_t i = 1; i < dex_locations_.size(); ++i) { + // TODO: Make everything properly std::string. + std::string image_name = CreateMultiImageName(dex_locations_[i], prefix, ".art"); + char_backing_storage_.push_front(base_img + image_name); + image_filenames_.push_back(char_backing_storage_.front().c_str()); + + std::string oat_name = CreateMultiImageName(dex_locations_[i], prefix, ".oat"); + char_backing_storage_.push_front(base_oat + oat_name); + oat_filenames_.push_back(char_backing_storage_.front().c_str()); + + if (!base_symbol_oat.empty()) { + char_backing_storage_.push_front(base_symbol_oat + oat_name); + oat_unstripped_.push_back(char_backing_storage_.front().c_str()); } - oat_unstripped_ = ImageSpace::ExpandMultiImageLocations(dex_locations_, oat_unstripped_[0]); } } + // Modify the input string in the following way: + // 0) Assume input is /a/b/c.d + // 1) Strip the path -> c.d + // 2) Inject prefix p -> pc.d + // 3) Replace suffix with s if it's "jar" -> d == "jar" -> pc.s + static std::string CreateMultiImageName(std::string in, + const std::string& prefix, + const char* replace_suffix) { + size_t last_dex_slash = in.rfind('/'); + if (last_dex_slash != std::string::npos) { + in = in.substr(last_dex_slash + 1); + } + if (!prefix.empty()) { + in = prefix + in; + } + if (android::base::EndsWith(in, ".jar")) { + in = in.substr(0, in.length() - strlen(".jar")) + + (replace_suffix != nullptr ? replace_suffix : ""); + } + return in; + } + void InsertCompileOptions(int argc, char** argv) { if (!avoid_storing_invocation_) { std::ostringstream oss; @@ -1431,8 +1497,11 @@ class Dex2Oat final { if (IsBootImage()) { // If we're compiling the boot image, store the boot classpath into the Key-Value store. - // We use this when loading the boot image. - key_value_store_->Put(OatHeader::kBootClassPathKey, android::base::Join(dex_locations_, ':')); + // We need this for the multi-image case. + key_value_store_->Put(OatHeader::kBootClassPathKey, + gc::space::ImageSpace::GetMultiImageBootClassPath(dex_locations_, + oat_filenames_, + image_filenames_)); } if (!IsBootImage()) { @@ -1444,7 +1513,8 @@ class Dex2Oat final { if (CompilerFilter::DependsOnImageChecksum(compiler_options_->GetCompilerFilter())) { TimingLogger::ScopedTiming t3("Loading image checksum", timings_); - std::vector<ImageSpace*> image_spaces = Runtime::Current()->GetHeap()->GetBootImageSpaces(); + std::vector<gc::space::ImageSpace*> image_spaces = + Runtime::Current()->GetHeap()->GetBootImageSpaces(); boot_image_checksum_ = image_spaces[0]->GetImageHeader().GetImageChecksum(); } else { boot_image_checksum_ = 0u; @@ -1883,7 +1953,7 @@ class Dex2Oat final { if (IsImage()) { if (IsAppImage() && image_base_ == 0) { gc::Heap* const heap = Runtime::Current()->GetHeap(); - for (ImageSpace* image_space : heap->GetBootImageSpaces()) { + for (gc::space::ImageSpace* image_space : heap->GetBootImageSpaces()) { image_base_ = std::max(image_base_, RoundUp( reinterpret_cast<uintptr_t>(image_space->GetImageHeader().GetOatFileEnd()), kPageSize)); diff --git a/dex2oat/linker/image_test.h b/dex2oat/linker/image_test.h index bd8cf5ad56..13fa0f033b 100644 --- a/dex2oat/linker/image_test.h +++ b/dex2oat/linker/image_test.h @@ -169,11 +169,10 @@ inline void ImageTest::DoCompile(ImageHeader::StorageMode storage_mode, { // Create a generic tmp file, to be the base of the .art and .oat temporary files. ScratchFile location; - std::vector<std::string> image_locations = - gc::space::ImageSpace::ExpandMultiImageLocations(out_helper.dex_file_locations, - location.GetFilename() + ".art"); - for (size_t i = 0u; i != class_path.size(); ++i) { - out_helper.image_locations.push_back(ScratchFile(image_locations[i])); + for (int i = 0; i < static_cast<int>(class_path.size()); ++i) { + std::string cur_location = + android::base::StringPrintf("%s-%d.art", location.GetFilename().c_str(), i); + out_helper.image_locations.push_back(ScratchFile(cur_location)); } } std::vector<std::string> image_filenames; @@ -224,7 +223,10 @@ inline void ImageTest::DoCompile(ImageHeader::StorageMode storage_mode, TimingLogger::ScopedTiming t("WriteElf", &timings); SafeMap<std::string, std::string> key_value_store; key_value_store.Put(OatHeader::kBootClassPathKey, - android::base::Join(out_helper.dex_file_locations, ':')); + gc::space::ImageSpace::GetMultiImageBootClassPath( + out_helper.dex_file_locations, + oat_filenames, + image_filenames)); std::vector<std::unique_ptr<ElfWriter>> elf_writers; std::vector<std::unique_ptr<OatWriter>> oat_writers; diff --git a/oatdump/oatdump_test.h b/oatdump/oatdump_test.h index dfa659b7e9..728939f93c 100644 --- a/oatdump/oatdump_test.h +++ b/oatdump/oatdump_test.h @@ -178,11 +178,6 @@ class OatDumpTest : public CommonRuntimeTest { expected_prefixes.push_back("InlineInfo"); } if (mode == kModeArt) { - exec_argv.push_back("--runtime-arg"); - exec_argv.push_back(GetClassPathOption("-Xbootclasspath:", GetLibCoreDexFileNames())); - exec_argv.push_back("--runtime-arg"); - exec_argv.push_back( - GetClassPathOption("-Xbootclasspath-locations:", GetLibCoreDexLocations())); exec_argv.push_back("--image=" + core_art_location_); exec_argv.push_back("--instruction-set=" + std::string( GetInstructionSetString(kRuntimeISA))); diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index e31fe6315b..c964dbcf59 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -1037,20 +1037,13 @@ bool ClassLinker::InitFromBootImage(std::string* error_msg) { runtime->SetSentinel(heap->AllocNonMovableObject<true>( self, java_lang_Object, java_lang_Object->GetObjectSize(), VoidFunctor())); - const std::vector<std::string>& boot_class_path = runtime->GetBootClassPath(); - if (boot_class_path.size() != spaces.size()) { - *error_msg = StringPrintf("Boot class path has %zu components but there are %zu image spaces.", - boot_class_path.size(), - spaces.size()); - return false; - } - for (size_t i = 0u, size = spaces.size(); i != size; ++i) { + for (gc::space::ImageSpace* image_space : spaces) { // Boot class loader, use a null handle. std::vector<std::unique_ptr<const DexFile>> dex_files; - if (!AddImageSpace(spaces[i], + if (!AddImageSpace(image_space, ScopedNullHandle<mirror::ClassLoader>(), - /*dex_elements=*/ nullptr, - /*dex_location=*/ boot_class_path[i].c_str(), + /*dex_elements=*/nullptr, + /*dex_location=*/nullptr, /*out*/&dex_files, error_msg)) { return false; @@ -1988,7 +1981,13 @@ bool ClassLinker::AddImageSpace( std::string dex_file_location(dex_cache->GetLocation()->ToModifiedUtf8()); // TODO: Only store qualified paths. // If non qualified, qualify it. - dex_file_location = OatFile::ResolveRelativeEncodedDexLocation(dex_location, dex_file_location); + if (dex_file_location.find('/') == std::string::npos) { + std::string dex_location_path = dex_location; + const size_t pos = dex_location_path.find_last_of('/'); + CHECK_NE(pos, std::string::npos); + dex_location_path = dex_location_path.substr(0, pos + 1); // Keep trailing '/' + dex_file_location = dex_location_path + dex_file_location; + } std::unique_ptr<const DexFile> dex_file = OpenOatDexFile(oat_file, dex_file_location.c_str(), error_msg); diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index 2f36d02eef..86135c1bc2 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -173,8 +173,6 @@ Heap::Heap(size_t initial_size, double foreground_heap_growth_multiplier, size_t capacity, size_t non_moving_space_capacity, - const std::vector<std::string>& boot_class_path, - const std::vector<std::string>& boot_class_path_locations, const std::string& image_file_name, const InstructionSet image_instruction_set, CollectorType foreground_collector_type, @@ -352,9 +350,7 @@ Heap::Heap(size_t initial_size, // Load image space(s). std::vector<std::unique_ptr<space::ImageSpace>> boot_image_spaces; MemMap heap_reservation; - if (space::ImageSpace::LoadBootImage(boot_class_path, - boot_class_path_locations, - image_file_name, + if (space::ImageSpace::LoadBootImage(image_file_name, image_instruction_set, heap_reservation_size, &boot_image_spaces, diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h index 8d81c11a43..411a4469d9 100644 --- a/runtime/gc/heap.h +++ b/runtime/gc/heap.h @@ -174,9 +174,7 @@ class Heap { double foreground_heap_growth_multiplier, size_t capacity, size_t non_moving_space_capacity, - const std::vector<std::string>& boot_class_path, - const std::vector<std::string>& boot_class_path_locations, - const std::string& image_file_name, + const std::string& original_image_file_name, InstructionSet image_instruction_set, CollectorType foreground_collector_type, CollectorType background_collector_type, diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc index 02ab50bded..e494bd681d 100644 --- a/runtime/gc/space/image_space.cc +++ b/runtime/gc/space/image_space.cc @@ -103,8 +103,9 @@ static int32_t ChooseRelocationOffsetDelta() { static bool GenerateImage(const std::string& image_filename, InstructionSet image_isa, std::string* error_msg) { - Runtime* runtime = Runtime::Current(); - const std::vector<std::string>& boot_class_path = runtime->GetBootClassPath(); + const std::string boot_class_path_string(Runtime::Current()->GetBootClassPathString()); + std::vector<std::string> boot_class_path; + Split(boot_class_path_string, ':', &boot_class_path); if (boot_class_path.empty()) { *error_msg = "Failed to generate image because no boot class path specified"; return false; @@ -124,11 +125,8 @@ static bool GenerateImage(const std::string& image_filename, image_option_string += image_filename; arg_vector.push_back(image_option_string); - const std::vector<std::string>& boot_class_path_locations = runtime->GetBootClassPathLocations(); - DCHECK_EQ(boot_class_path.size(), boot_class_path_locations.size()); - for (size_t i = 0u; i < boot_class_path.size(); i++) { + for (size_t i = 0; i < boot_class_path.size(); i++) { arg_vector.push_back(std::string("--dex-file=") + boot_class_path[i]); - arg_vector.push_back(std::string("--dex-location=") + boot_class_path_locations[i]); } std::string oat_file_option_string("--oat-file="); @@ -1207,13 +1205,8 @@ class ImageSpace::Loader { class ImageSpace::BootImageLoader { public: - BootImageLoader(const std::vector<std::string>& boot_class_path, - const std::vector<std::string>& boot_class_path_locations, - const std::string& image_location, - InstructionSet image_isa) - : boot_class_path_(boot_class_path), - boot_class_path_locations_(boot_class_path_locations), - image_location_(image_location), + BootImageLoader(const std::string& image_location, InstructionSet image_isa) + : image_location_(image_location), image_isa_(image_isa), is_zygote_(Runtime::Current()->IsZygote()), has_system_(false), @@ -1261,8 +1254,10 @@ class ImageSpace::BootImageLoader { /*out*/std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_) { TimingLogger logger(__PRETTY_FUNCTION__, /*precise=*/ true, VLOG_IS_ON(image)); std::string filename = GetSystemImageFilename(image_location_.c_str(), image_isa_); - std::vector<std::string> locations = - ExpandMultiImageLocations(boot_class_path_locations_, image_location_); + std::vector<std::string> locations; + if (!GetBootClassPathImageLocations(image_location_, filename, &locations, error_msg)) { + return false; + } uint32_t image_start; uint32_t image_end; if (!GetBootImageAddressRange(filename, &image_start, &image_end, error_msg)) { @@ -1295,16 +1290,9 @@ class ImageSpace::BootImageLoader { return false; } } - for (size_t i = 0u, size = spaces.size(); i != size; ++i) { - std::string expected_boot_class_path = - (i == 0u) ? android::base::Join(boot_class_path_locations_, ':') : std::string(); - if (!OpenOatFile(spaces[i].get(), - boot_class_path_[i], - expected_boot_class_path, - /*validate_oat_file=*/ false, - &logger, - &image_reservation, - error_msg)) { + for (std::unique_ptr<ImageSpace>& space : spaces) { + static constexpr bool kValidateOatFile = false; + if (!OpenOatFile(space.get(), kValidateOatFile, &logger, &image_reservation, error_msg)) { return false; } } @@ -1333,8 +1321,10 @@ class ImageSpace::BootImageLoader { /*out*/std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_) { TimingLogger logger(__PRETTY_FUNCTION__, /*precise=*/ true, VLOG_IS_ON(image)); DCHECK(DalvikCacheExists()); - std::vector<std::string> locations = - ExpandMultiImageLocations(boot_class_path_locations_, image_location_); + std::vector<std::string> locations; + if (!GetBootClassPathImageLocations(image_location_, cache_filename_, &locations, error_msg)) { + return false; + } uint32_t image_start; uint32_t image_end; if (!GetBootImageAddressRange(cache_filename_, &image_start, &image_end, error_msg)) { @@ -1376,16 +1366,8 @@ class ImageSpace::BootImageLoader { return false; } } - for (size_t i = 0u, size = spaces.size(); i != size; ++i) { - std::string expected_boot_class_path = - (i == 0u) ? android::base::Join(boot_class_path_locations_, ':') : std::string(); - if (!OpenOatFile(spaces[i].get(), - boot_class_path_[i], - expected_boot_class_path, - validate_oat_file, - &logger, - &image_reservation, - error_msg)) { + for (std::unique_ptr<ImageSpace>& space : spaces) { + if (!OpenOatFile(space.get(), validate_oat_file, &logger, &image_reservation, error_msg)) { return false; } } @@ -1905,6 +1887,8 @@ class ImageSpace::BootImageLoader { DCHECK(!spaces.empty()); ImageSpace* space = spaces[0].get(); const ImageHeader& image_header = space->GetImageHeader(); + // Use oat_file_non_owned_ from the `space` to set the runtime methods. + runtime->SetInstructionSet(space->oat_file_non_owned_->GetOatHeader().GetInstructionSet()); runtime->SetResolutionMethod(image_header.GetImageMethod(ImageHeader::kResolutionMethod)); runtime->SetImtConflictMethod(image_header.GetImageMethod(ImageHeader::kImtConflictMethod)); runtime->SetImtUnimplementedMethod( @@ -1968,8 +1952,6 @@ class ImageSpace::BootImageLoader { } bool OpenOatFile(ImageSpace* space, - const std::string& dex_filename, - const std::string& expected_boot_class_path, bool validate_oat_file, TimingLogger* logger, /*inout*/MemMap* image_reservation, @@ -1985,15 +1967,13 @@ class ImageSpace::BootImageLoader { TimingLogger::ScopedTiming timing("OpenOatFile", logger); std::string oat_filename = ImageHeader::GetOatLocationFromImageLocation(space->GetImageFilename()); - std::string oat_location = - ImageHeader::GetOatLocationFromImageLocation(space->GetImageLocation()); oat_file.reset(OatFile::Open(/*zip_fd=*/ -1, oat_filename, - oat_location, + oat_filename, !Runtime::Current()->IsAotCompiler(), /*low_4gb=*/ false, - /*abs_dex_location=*/ dex_filename.c_str(), + /*abs_dex_location=*/ nullptr, image_reservation, error_msg)); if (oat_file == nullptr) { @@ -2014,17 +1994,6 @@ class ImageSpace::BootImageLoader { space->GetName()); return false; } - const char* oat_boot_class_path = - oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kBootClassPathKey); - oat_boot_class_path = (oat_boot_class_path != nullptr) ? oat_boot_class_path : ""; - if (expected_boot_class_path != oat_boot_class_path) { - *error_msg = StringPrintf("Failed to match oat boot class path %s to expected " - "boot class path %s in image %s", - oat_boot_class_path, - expected_boot_class_path.c_str(), - space->GetName()); - return false; - } ptrdiff_t relocation_diff = space->Begin() - image_header.GetImageBegin(); CHECK(image_header.GetOatDataBegin() != nullptr); uint8_t* oat_data_begin = image_header.GetOatDataBegin() + relocation_diff; @@ -2050,6 +2019,37 @@ class ImageSpace::BootImageLoader { return true; } + // Extract boot class path from oat file associated with `image_filename` + // and list all associated image locations. + static bool GetBootClassPathImageLocations(const std::string& image_location, + const std::string& image_filename, + /*out*/ std::vector<std::string>* all_locations, + /*out*/ std::string* error_msg) { + std::string oat_filename = ImageHeader::GetOatLocationFromImageLocation(image_filename); + std::unique_ptr<OatFile> oat_file(OatFile::Open(/*zip_fd=*/ -1, + oat_filename, + oat_filename, + /*executable=*/ false, + /*low_4gb=*/ false, + /*abs_dex_location=*/ nullptr, + /*reservation=*/ nullptr, + error_msg)); + if (oat_file == nullptr) { + *error_msg = StringPrintf("Failed to open oat file '%s' for image file %s: %s", + oat_filename.c_str(), + image_filename.c_str(), + error_msg->c_str()); + return false; + } + const OatHeader& oat_header = oat_file->GetOatHeader(); + const char* boot_classpath = oat_header.GetStoreValueByKey(OatHeader::kBootClassPathKey); + all_locations->push_back(image_location); + if (boot_classpath != nullptr && boot_classpath[0] != 0) { + ExtractMultiImageLocations(image_location, boot_classpath, all_locations); + } + return true; + } + bool GetBootImageAddressRange(const std::string& filename, /*out*/uint32_t* start, /*out*/uint32_t* end, @@ -2116,8 +2116,6 @@ class ImageSpace::BootImageLoader { return true; } - const std::vector<std::string>& boot_class_path_; - const std::vector<std::string>& boot_class_path_locations_; const std::string& image_location_; InstructionSet image_isa_; bool is_zygote_; @@ -2165,8 +2163,6 @@ static bool CheckSpace(const std::string& cache_filename, std::string* error_msg } bool ImageSpace::LoadBootImage( - const std::vector<std::string>& boot_class_path, - const std::vector<std::string>& boot_class_path_locations, const std::string& image_location, const InstructionSet image_isa, size_t extra_reservation_size, @@ -2184,7 +2180,7 @@ bool ImageSpace::LoadBootImage( return false; } - BootImageLoader loader(boot_class_path, boot_class_path_locations, image_location, image_isa); + BootImageLoader loader(image_location, image_isa); // Step 0: Extra zygote work. @@ -2345,6 +2341,57 @@ void ImageSpace::Dump(std::ostream& os) const { << ",name=\"" << GetName() << "\"]"; } +std::string ImageSpace::GetMultiImageBootClassPath( + const std::vector<std::string>& dex_locations, + const std::vector<std::string>& oat_filenames, + const std::vector<std::string>& image_filenames) { + DCHECK_GT(oat_filenames.size(), 1u); + // If the image filename was adapted (e.g., for our tests), we need to change this here, + // too, but need to strip all path components (they will be re-established when loading). + // For example, dex location + // /system/framework/core-libart.art + // with image name + // out/target/product/taimen/dex_bootjars/system/framework/arm64/boot-core-libart.art + // yields boot class path component + // /system/framework/boot-core-libart.art . + std::ostringstream bootcp_oss; + bool first_bootcp = true; + for (size_t i = 0; i < dex_locations.size(); ++i) { + if (!first_bootcp) { + bootcp_oss << ":"; + } + + std::string dex_loc = dex_locations[i]; + std::string image_filename = image_filenames[i]; + + // Use the dex_loc path, but the image_filename name (without path elements). + size_t dex_last_slash = dex_loc.rfind('/'); + + // npos is max(size_t). That makes this a bit ugly. + size_t image_last_slash = image_filename.rfind('/'); + size_t image_last_at = image_filename.rfind('@'); + size_t image_last_sep = (image_last_slash == std::string::npos) + ? image_last_at + : (image_last_at == std::string::npos) + ? image_last_slash + : std::max(image_last_slash, image_last_at); + // Note: whenever image_last_sep == npos, +1 overflow means using the full string. + + if (dex_last_slash == std::string::npos) { + dex_loc = image_filename.substr(image_last_sep + 1); + } else { + dex_loc = dex_loc.substr(0, dex_last_slash + 1) + + image_filename.substr(image_last_sep + 1); + } + + // Image filenames already end with .art, no need to replace. + + bootcp_oss << dex_loc; + first_bootcp = false; + } + return bootcp_oss.str(); +} + bool ImageSpace::ValidateOatFile(const OatFile& oat_file, std::string* error_msg) { const ArtDexFileLoader dex_file_loader; for (const OatDexFile* oat_dex_file : oat_file.GetOatDexFiles()) { @@ -2405,55 +2452,46 @@ bool ImageSpace::ValidateOatFile(const OatFile& oat_file, std::string* error_msg return true; } -std::vector<std::string> ImageSpace::ExpandMultiImageLocations( - const std::vector<std::string>& dex_locations, - const std::string& image_location) { - DCHECK(!dex_locations.empty()); - - // Find the path. - size_t last_slash = image_location.rfind('/'); - CHECK_NE(last_slash, std::string::npos); +void ImageSpace::ExtractMultiImageLocations(const std::string& input_image_file_name, + const std::string& boot_classpath, + std::vector<std::string>* image_file_names) { + DCHECK(image_file_names != nullptr); - // We also need to honor path components that were encoded through '@'. Otherwise the loading - // code won't be able to find the images. - if (image_location.find('@', last_slash) != std::string::npos) { - last_slash = image_location.rfind('@'); - } + std::vector<std::string> images; + Split(boot_classpath, ':', &images); - // Find the dot separating the primary image name from the extension. - size_t last_dot = image_location.rfind('.'); - // Extract the extension and base (the path and primary image name). - std::string extension; - std::string base = image_location; - if (last_dot != std::string::npos && last_dot > last_slash) { - extension = image_location.substr(last_dot); // Including the dot. - base.resize(last_dot); - } - // For non-empty primary image name, add '-' to the `base`. - if (last_slash + 1u != base.size()) { - base += '-'; + // Add the rest into the list. We have to adjust locations, possibly: + // + // For example, image_file_name is /a/b/c/d/e.art + // images[0] is f/c/d/e.art + // ---------------------------------------------- + // images[1] is g/h/i/j.art -> /a/b/h/i/j.art + const std::string& first_image = images[0]; + // Length of common suffix. + size_t common = 0; + while (common < input_image_file_name.size() && + common < first_image.size() && + *(input_image_file_name.end() - common - 1) == *(first_image.end() - common - 1)) { + ++common; } - - std::vector<std::string> locations; - locations.reserve(dex_locations.size()); - locations.push_back(image_location); - - // Now create the other names. Use a counted loop to skip the first one. - for (size_t i = 1u; i < dex_locations.size(); ++i) { - // Replace path with `base` (i.e. image path and prefix) and replace the original - // extension (if any) with `extension`. - std::string name = dex_locations[i]; - size_t last_dex_slash = name.rfind('/'); - if (last_dex_slash != std::string::npos) { - name = name.substr(last_dex_slash + 1); - } - size_t last_dex_dot = name.rfind('.'); - if (last_dex_dot != std::string::npos) { - name.resize(last_dex_dot); - } - locations.push_back(base + name + extension); + // We want to replace the prefix of the input image with the prefix of the boot class path. + // This handles the case where the image file contains @ separators. + // Example image_file_name is oats/system@framework@boot.art + // images[0] is .../arm/boot.art + // means that the image name prefix will be oats/system@framework@ + // so that the other images are openable. + const size_t old_prefix_length = first_image.size() - common; + const std::string new_prefix = input_image_file_name.substr( + 0, + input_image_file_name.size() - common); + + // Apply pattern to images[1] .. images[n]. + for (size_t i = 1; i < images.size(); ++i) { + const std::string& image = images[i]; + CHECK_GT(image.length(), old_prefix_length); + std::string suffix = image.substr(old_prefix_length); + image_file_names->push_back(new_prefix + suffix); } - return locations; } void ImageSpace::DumpSections(std::ostream& os) const { diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h index 05e7fa5cca..aa45ed3952 100644 --- a/runtime/gc/space/image_space.h +++ b/runtime/gc/space/image_space.h @@ -39,11 +39,9 @@ class ImageSpace : public MemMapSpace { // Load boot image spaces from a primary image file for a specified instruction set. // // On successful return, the loaded spaces are added to boot_image_spaces (which must be - // empty on entry) and `extra_reservation` is set to the requested reservation located - // after the end of the last loaded oat file. + // empty on entry) and oat_file_end is updated with the (page-aligned) end of the last + // oat file. static bool LoadBootImage( - const std::vector<std::string>& boot_class_path, - const std::vector<std::string>& boot_class_path_locations, const std::string& image_location, const InstructionSet image_isa, size_t extra_reservation_size, @@ -124,10 +122,15 @@ class ImageSpace : public MemMapSpace { bool* has_data, bool *is_global_cache); - // Expand a single image location to multi-image locations based on the dex locations. - static std::vector<std::string> ExpandMultiImageLocations( - const std::vector<std::string>& dex_locations, - const std::string& image_location); + // Use the input image filename to adapt the names in the given boot classpath to establish + // complete locations for secondary images. + static void ExtractMultiImageLocations(const std::string& input_image_file_name, + const std::string& boot_classpath, + std::vector<std::string>* image_filenames); + + static std::string GetMultiImageBootClassPath(const std::vector<std::string>& dex_locations, + const std::vector<std::string>& oat_filenames, + const std::vector<std::string>& image_filenames); // Returns true if the dex checksums in the given oat file match the // checksums of the original dex files on disk. This is intended to be used diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc index 4fa7271ff4..e292a7612c 100644 --- a/runtime/interpreter/unstarted_runtime.cc +++ b/runtime/interpreter/unstarted_runtime.cc @@ -571,9 +571,12 @@ static void GetResourceAsStream(Thread* self, Runtime* runtime = Runtime::Current(); - const std::vector<std::string>& boot_class_path = Runtime::Current()->GetBootClassPath(); - if (boot_class_path.empty()) { - AbortTransactionOrFail(self, "Boot classpath not set"); + std::vector<std::string> split; + Split(runtime->GetBootClassPathString(), ':', &split); + if (split.empty()) { + AbortTransactionOrFail(self, + "Boot classpath not set or split error:: %s", + runtime->GetBootClassPathString().c_str()); return; } @@ -581,7 +584,7 @@ static void GetResourceAsStream(Thread* self, size_t map_size; std::string last_error_msg; // Only store the last message (we could concatenate). - for (const std::string& jar_file : boot_class_path) { + for (const std::string& jar_file : split) { mem_map = FindAndExtractEntry(jar_file, resource_cstr, &map_size, &last_error_msg); if (mem_map.IsValid()) { break; diff --git a/runtime/jdwp/jdwp_handler.cc b/runtime/jdwp/jdwp_handler.cc index 37365ff9b5..d31f166869 100644 --- a/runtime/jdwp/jdwp_handler.cc +++ b/runtime/jdwp/jdwp_handler.cc @@ -292,7 +292,8 @@ static JdwpError VM_ClassPaths(JdwpState*, Request*, ExpandBuf* pReply) expandBufAddUtf8String(pReply, str); } - std::vector<std::string> boot_class_path = Runtime::Current()->GetBootClassPath(); + std::vector<std::string> boot_class_path; + Split(Runtime::Current()->GetBootClassPathString(), ':', &boot_class_path); expandBufAdd4BE(pReply, boot_class_path.size()); for (const std::string& str : boot_class_path) { expandBufAddUtf8String(pReply, str); diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc index 3e5003ce13..e213dc79b8 100644 --- a/runtime/native/dalvik_system_VMRuntime.cc +++ b/runtime/native/dalvik_system_VMRuntime.cc @@ -24,8 +24,7 @@ extern "C" void android_set_application_target_sdk_version(uint32_t version); #include <limits.h> #include "nativehelper/scoped_utf_chars.h" -#include <android-base/stringprintf.h> -#include <android-base/strings.h> +#include "android-base/stringprintf.h" #include "arch/instruction_set.h" #include "art_method-inl.h" @@ -223,8 +222,7 @@ static const char* DefaultToDot(const std::string& class_path) { } static jstring VMRuntime_bootClassPath(JNIEnv* env, jobject) { - std::string boot_class_path = android::base::Join(Runtime::Current()->GetBootClassPath(), ':'); - return env->NewStringUTF(DefaultToDot(boot_class_path)); + return env->NewStringUTF(DefaultToDot(Runtime::Current()->GetBootClassPathString())); } static jstring VMRuntime_classPath(JNIEnv* env, jobject) { diff --git a/runtime/oat.h b/runtime/oat.h index b09c81e3ad..ee46f426cf 100644 --- a/runtime/oat.h +++ b/runtime/oat.h @@ -31,8 +31,8 @@ class InstructionSetFeatures; class PACKED(4) OatHeader { public: static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' }; - // Last oat version changed reason: Pass boot class path to LoadBootImage. - static constexpr uint8_t kOatVersion[] = { '1', '6', '5', '\0' }; + // Last oat version changed reason: Image checksums. + static constexpr uint8_t kOatVersion[] = { '1', '6', '4', '\0' }; static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline"; static constexpr const char* kDebuggableKey = "debuggable"; diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc index 17ff3a244d..29b569050c 100644 --- a/runtime/parsed_options.cc +++ b/runtime/parsed_options.cc @@ -20,7 +20,6 @@ #include <sstream> #include <android-base/logging.h> -#include <android-base/strings.h> #include "base/file_utils.h" #include "base/macros.h" @@ -79,7 +78,7 @@ std::unique_ptr<RuntimeParser> ParsedOptions::MakeParser(bool ignore_unrecognize .Define("-showversion") .IntoKey(M::ShowVersion) .Define("-Xbootclasspath:_") - .WithType<ParseStringList<':'>>() // std::vector<std::string>, split by : + .WithType<std::string>() .IntoKey(M::BootClassPath) .Define("-Xbootclasspath-locations:_") .WithType<ParseStringList<':'>>() // std::vector<std::string>, split by : @@ -514,7 +513,7 @@ bool ParsedOptions::DoParse(const RuntimeOptions& options, GetInstructionSetString(kRuntimeISA)); Exit(0); } else if (args.Exists(M::BootClassPath)) { - LOG(INFO) << "setting boot class path to " << args.Get(M::BootClassPath)->Join(); + LOG(INFO) << "setting boot class path to " << *args.Get(M::BootClassPath); } if (args.GetOrDefault(M::Interpret)) { @@ -526,9 +525,8 @@ bool ParsedOptions::DoParse(const RuntimeOptions& options, } // Set a default boot class path if we didn't get an explicit one via command line. - const char* env_bcp = getenv("BOOTCLASSPATH"); - if (env_bcp != nullptr) { - args.SetIfMissing(M::BootClassPath, ParseStringList<':'>::Split(env_bcp)); + if (getenv("BOOTCLASSPATH") != nullptr) { + args.SetIfMissing(M::BootClassPath, std::string(getenv("BOOTCLASSPATH"))); } // Set a default class path if we didn't get an explicit one via command line. @@ -588,20 +586,22 @@ bool ParsedOptions::DoParse(const RuntimeOptions& options, args.Set(M::BackgroundGc, BackgroundGcOption { background_collector_type_ }); } - const ParseStringList<':'>* boot_class_path_locations = args.Get(M::BootClassPathLocations); - if (boot_class_path_locations != nullptr && boot_class_path_locations->Size() != 0u) { - const ParseStringList<':'>* boot_class_path = args.Get(M::BootClassPath); - if (boot_class_path == nullptr || - boot_class_path_locations->Size() != boot_class_path->Size()) { - Usage("The number of boot class path files does not match" - " the number of boot class path locations given\n" - " boot class path files (%zu): %s\n" - " boot class path locations (%zu): %s\n", - (boot_class_path != nullptr) ? boot_class_path->Size() : 0u, - (boot_class_path != nullptr) ? boot_class_path->Join().c_str() : "<nil>", - boot_class_path_locations->Size(), - boot_class_path_locations->Join().c_str()); - return false; + auto boot_class_path_string = args.GetOrDefault(M::BootClassPath); + { + auto&& boot_class_path = args.GetOrDefault(M::BootClassPath); + auto&& boot_class_path_locations = args.GetOrDefault(M::BootClassPathLocations); + if (args.Exists(M::BootClassPathLocations)) { + size_t boot_class_path_count = ParseStringList<':'>::Split(boot_class_path).Size(); + + if (boot_class_path_count != boot_class_path_locations.Size()) { + Usage("The number of boot class path files does not match" + " the number of boot class path locations given\n" + " boot class path files (%zu): %s\n" + " boot class path locations (%zu): %s\n", + boot_class_path.size(), boot_class_path_string.c_str(), + boot_class_path_locations.Size(), boot_class_path_locations.Join().c_str()); + return false; + } } } diff --git a/runtime/parsed_options_test.cc b/runtime/parsed_options_test.cc index cbb7b825d3..705cc6c5e2 100644 --- a/runtime/parsed_options_test.cc +++ b/runtime/parsed_options_test.cc @@ -40,7 +40,8 @@ TEST_F(ParsedOptionsTest, ParsedOptions) { boot_class_path += "-Xbootclasspath:"; bool first_dex_file = true; - for (const std::string &dex_file_name : CommonRuntimeTest::GetLibCoreDexFileNames()) { + for (const std::string &dex_file_name : + CommonRuntimeTest::GetLibCoreDexFileNames()) { if (!first_dex_file) { class_path += ":"; } else { @@ -49,8 +50,6 @@ TEST_F(ParsedOptionsTest, ParsedOptions) { class_path += dex_file_name; } boot_class_path += class_path; - std::vector<std::string> expected_boot_class_path; - Split(class_path, ':', &expected_boot_class_path); RuntimeOptions options; options.push_back(std::make_pair(boot_class_path.c_str(), nullptr)); @@ -79,11 +78,9 @@ TEST_F(ParsedOptionsTest, ParsedOptions) { using Opt = RuntimeArgumentMap; #define EXPECT_PARSED_EQ(expected, actual_key) EXPECT_EQ(expected, map.GetOrDefault(actual_key)) -#define EXPECT_PARSED_EQ_AS_STRING_VECTOR(expected, actual_key) \ - EXPECT_EQ(expected, static_cast<std::vector<std::string>>(map.GetOrDefault(actual_key))) #define EXPECT_PARSED_EXISTS(actual_key) EXPECT_TRUE(map.Exists(actual_key)) - EXPECT_PARSED_EQ_AS_STRING_VECTOR(expected_boot_class_path, Opt::BootClassPath); + EXPECT_PARSED_EQ(class_path, Opt::BootClassPath); EXPECT_PARSED_EQ(class_path, Opt::ClassPath); EXPECT_PARSED_EQ(std::string("boot_image"), Opt::Image); EXPECT_PARSED_EXISTS(Opt::CheckJni); diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 11e0bf45f9..8e3d71a79e 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -1097,45 +1097,7 @@ bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) { Monitor::Init(runtime_options.GetOrDefault(Opt::LockProfThreshold), runtime_options.GetOrDefault(Opt::StackDumpLockProfThreshold)); - image_location_ = runtime_options.GetOrDefault(Opt::Image); - SetInstructionSet(runtime_options.GetOrDefault(Opt::ImageInstructionSet)); - boot_class_path_ = runtime_options.ReleaseOrDefault(Opt::BootClassPath); - boot_class_path_locations_ = runtime_options.ReleaseOrDefault(Opt::BootClassPathLocations); - DCHECK(boot_class_path_locations_.empty() || - boot_class_path_locations_.size() == boot_class_path_.size()); - if (boot_class_path_.empty()) { - // Try to extract the boot class path from the system boot image. - if (image_location_.empty()) { - LOG(ERROR) << "Empty boot class path, cannot continue without image."; - return false; - } - std::string system_oat_filename = ImageHeader::GetOatLocationFromImageLocation( - GetSystemImageFilename(image_location_.c_str(), instruction_set_)); - std::string system_oat_location = ImageHeader::GetOatLocationFromImageLocation(image_location_); - std::string error_msg; - std::unique_ptr<OatFile> oat_file(OatFile::Open(/*zip_fd=*/ -1, - system_oat_filename, - system_oat_location, - /*executable=*/ false, - /*low_4gb=*/ false, - /*abs_dex_location=*/ nullptr, - /*reservation=*/ nullptr, - &error_msg)); - if (oat_file == nullptr) { - LOG(ERROR) << "Could not open boot oat file for extracting boot class path: " << error_msg; - return false; - } - const OatHeader& oat_header = oat_file->GetOatHeader(); - const char* oat_boot_class_path = oat_header.GetStoreValueByKey(OatHeader::kBootClassPathKey); - if (oat_boot_class_path != nullptr) { - Split(oat_boot_class_path, ':', &boot_class_path_); - } - if (boot_class_path_.empty()) { - LOG(ERROR) << "Boot class path missing from boot image oat file " << oat_file->GetLocation(); - return false; - } - } - + boot_class_path_string_ = runtime_options.ReleaseOrDefault(Opt::BootClassPath); class_path_string_ = runtime_options.ReleaseOrDefault(Opt::ClassPath); properties_ = runtime_options.ReleaseOrDefault(Opt::PropertiesList); @@ -1161,6 +1123,7 @@ bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) { } } image_compiler_options_ = runtime_options.ReleaseOrDefault(Opt::ImageCompilerOptions); + image_location_ = runtime_options.GetOrDefault(Opt::Image); max_spins_before_thin_lock_inflation_ = runtime_options.GetOrDefault(Opt::MaxSpinsBeforeThinLockInflation); @@ -1229,10 +1192,8 @@ bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) { foreground_heap_growth_multiplier, runtime_options.GetOrDefault(Opt::MemoryMaximumSize), runtime_options.GetOrDefault(Opt::NonMovingSpaceCapacity), - GetBootClassPath(), - GetBootClassPathLocations(), - image_location_, - instruction_set_, + runtime_options.GetOrDefault(Opt::Image), + runtime_options.GetOrDefault(Opt::ImageInstructionSet), // Override the collector type to CC if the read barrier config. kUseReadBarrier ? gc::kCollectorTypeCC : xgc_option.collector_type_, kUseReadBarrier ? BackgroundGcOption(gc::kCollectorTypeCCBackground) @@ -1432,6 +1393,16 @@ bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) { image_space->VerifyImageAllocations(); } } + if (boot_class_path_string_.empty()) { + // The bootclasspath is not explicitly specified: construct it from the loaded dex files. + const std::vector<const DexFile*>& boot_class_path = GetClassLinker()->GetBootClassPath(); + std::vector<std::string> dex_locations; + dex_locations.reserve(boot_class_path.size()); + for (const DexFile* dex_file : boot_class_path) { + dex_locations.push_back(dex_file->GetLocation()); + } + boot_class_path_string_ = android::base::Join(dex_locations, ':'); + } { ScopedTrace trace2("AddImageStringsToTable"); for (gc::space::ImageSpace* image_space : heap_->GetBootImageSpaces()) { @@ -1444,12 +1415,24 @@ bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) { DeoptimizeBootImage(); } } else { + std::vector<std::string> dex_filenames; + Split(boot_class_path_string_, ':', &dex_filenames); + + std::vector<std::string> dex_locations; + if (!runtime_options.Exists(Opt::BootClassPathLocations)) { + dex_locations = dex_filenames; + } else { + dex_locations = runtime_options.GetOrDefault(Opt::BootClassPathLocations); + CHECK_EQ(dex_filenames.size(), dex_locations.size()); + } + std::vector<std::unique_ptr<const DexFile>> boot_class_path; if (runtime_options.Exists(Opt::BootClassPathDexList)) { boot_class_path.swap(*runtime_options.GetOrDefault(Opt::BootClassPathDexList)); } else { - OpenDexFiles(GetBootClassPath(), GetBootClassPathLocations(), &boot_class_path); + OpenDexFiles(dex_filenames, dex_locations, &boot_class_path); } + instruction_set_ = runtime_options.GetOrDefault(Opt::ImageInstructionSet); if (!class_linker_->InitWithoutImage(std::move(boot_class_path), &error_msg)) { LOG(ERROR) << "Could not initialize without image: " << error_msg; return false; diff --git a/runtime/runtime.h b/runtime/runtime.h index b76a658b49..45333761af 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -243,14 +243,8 @@ class Runtime { ~Runtime(); - const std::vector<std::string>& GetBootClassPath() const { - return boot_class_path_; - } - - const std::vector<std::string>& GetBootClassPathLocations() const { - DCHECK(boot_class_path_locations_.empty() || - boot_class_path_locations_.size() == boot_class_path_.size()); - return boot_class_path_locations_.empty() ? boot_class_path_ : boot_class_path_locations_; + const std::string& GetBootClassPathString() const { + return boot_class_path_string_; } const std::string& GetClassPathString() const { @@ -872,8 +866,7 @@ class Runtime { std::vector<std::string> image_compiler_options_; std::string image_location_; - std::vector<std::string> boot_class_path_; - std::vector<std::string> boot_class_path_locations_; + std::string boot_class_path_string_; std::string class_path_string_; std::vector<std::string> properties_; diff --git a/runtime/runtime_options.def b/runtime/runtime_options.def index 2b2919eff4..5cec309453 100644 --- a/runtime/runtime_options.def +++ b/runtime/runtime_options.def @@ -37,7 +37,7 @@ RUNTIME_OPTIONS_KEY (Unit, Zygote) RUNTIME_OPTIONS_KEY (Unit, Help) RUNTIME_OPTIONS_KEY (Unit, ShowVersion) -RUNTIME_OPTIONS_KEY (ParseStringList<':'>,BootClassPath) // std::vector<std::string> +RUNTIME_OPTIONS_KEY (std::string, BootClassPath) RUNTIME_OPTIONS_KEY (ParseStringList<':'>,BootClassPathLocations) // std::vector<std::string> RUNTIME_OPTIONS_KEY (std::string, ClassPath) RUNTIME_OPTIONS_KEY (std::string, Image) diff --git a/tools/run-libcore-tests.sh b/tools/run-libcore-tests.sh index 63f1fce13f..2d39b2a9f8 100755 --- a/tools/run-libcore-tests.sh +++ b/tools/run-libcore-tests.sh @@ -46,21 +46,6 @@ function cparg { done } -function boot_classpath_arg { - local dir="$1" - local suffix="$2" - shift 2 - printf -- "--vm-arg -Xbootclasspath" - for var - do - printf -- ":${dir}/${var}${suffix}.jar"; - done -} - -# Note: This must match the TEST_CORE_JARS in Android.common_path.mk -# because that's what we use for compiling the core.art image. -BOOT_CLASSPATH_JARS="core-oj core-libart core-simple conscrypt okhttp bouncycastle" - DEPS="core-tests jsr166-tests mockito-target" for lib in $DEPS @@ -125,7 +110,6 @@ while true; do if [[ "$1" == "--mode=device" ]]; then device_mode=true vogar_args="$vogar_args --vm-arg -Ximage:/data/art-test/core.art" - vogar_args="$vogar_args $(boot_classpath_arg /system/framework -testdex $BOOT_CLASSPATH_JARS)" shift elif [[ "$1" == "--mode=host" ]]; then # We explicitly give a wrong path for the image, to ensure vogar |