Fix `ClassLinker::AppendToBootClassPath` usages. am: 28451dc192 am: 678b965707
Original change: https://android-review.googlesource.com/c/platform/art/+/2196996
Change-Id: I8b82cbaa5f02351d1f4d558ec8008e0fe6dc63ce
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/dex2oat/linker/image_test.h b/dex2oat/linker/image_test.h
index b570d99..52e53e6 100644
--- a/dex2oat/linker/image_test.h
+++ b/dex2oat/linker/image_test.h
@@ -63,6 +63,7 @@
struct CompilationHelper {
std::vector<std::string> dex_file_locations;
std::vector<ScratchFile> image_locations;
+ std::string extra_dex;
std::vector<std::unique_ptr<const DexFile>> extra_dex_files;
std::vector<ScratchFile> image_files;
std::vector<ScratchFile> oat_files;
@@ -150,18 +151,11 @@
inline void ImageTest::DoCompile(ImageHeader::StorageMode storage_mode,
/*out*/ CompilationHelper& out_helper) {
CompilerDriver* driver = compiler_driver_.get();
+ Runtime::Current()->AppendToBootClassPath(
+ out_helper.extra_dex, out_helper.extra_dex, out_helper.extra_dex_files);
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
std::vector<const DexFile*> class_path = class_linker->GetBootClassPath();
- for (const std::unique_ptr<const DexFile>& dex_file : out_helper.extra_dex_files) {
- {
- ScopedObjectAccess soa(Thread::Current());
- // Inject in boot class path so that the compiler driver can see it.
- class_linker->AppendToBootClassPath(soa.Self(), dex_file.get());
- }
- class_path.push_back(dex_file.get());
- }
-
// Enable write for dex2dex.
for (const DexFile* dex_file : class_path) {
out_helper.dex_file_locations.push_back(dex_file->GetLocation());
@@ -368,6 +362,7 @@
compiler_options_->SetMaxImageBlockSize(max_image_block_size);
image_classes_.clear();
if (!extra_dex.empty()) {
+ helper.extra_dex = extra_dex;
helper.extra_dex_files = OpenTestDexFiles(extra_dex.c_str());
}
DoCompile(storage_mode, helper);
diff --git a/openjdkjvmti/ti_class_loader.cc b/openjdkjvmti/ti_class_loader.cc
index d0a6634..cf82534 100644
--- a/openjdkjvmti/ti_class_loader.cc
+++ b/openjdkjvmti/ti_class_loader.cc
@@ -66,7 +66,8 @@
art::ScopedObjectAccessUnchecked soa(self);
art::StackHandleScope<3> hs(self);
if (art::ClassLinker::IsBootClassLoader(soa, loader.Get())) {
- art::Runtime::Current()->GetClassLinker()->AppendToBootClassPath(self, dex_file);
+ art::Runtime::Current()->AppendToBootClassPath(
+ dex_file->GetLocation(), dex_file->GetLocation(), {dex_file});
return true;
}
art::Handle<art::mirror::Object> java_dex_file_obj(
diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc
index 59f93c5..2521ff3 100644
--- a/openjdkjvmti/ti_redefine.cc
+++ b/openjdkjvmti/ti_redefine.cc
@@ -512,8 +512,15 @@
art::MemMap Redefiner::MoveDataToMemMap(const std::string& original_location,
art::ArrayRef<const unsigned char> data,
std::string* error_msg) {
+ std::string modified_location = StringPrintf("%s-transformed", original_location.c_str());
+ // A dangling multi-dex location appended to bootclasspath can cause inaccuracy in oat file
+ // validation. For simplicity, just convert it to a normal location.
+ size_t pos = modified_location.find(art::DexFileLoader::kMultiDexSeparator);
+ if (pos != std::string::npos) {
+ modified_location[pos] = '-';
+ }
art::MemMap map = art::MemMap::MapAnonymous(
- StringPrintf("%s-transformed", original_location.c_str()).c_str(),
+ modified_location.c_str(),
data.size(),
PROT_READ|PROT_WRITE,
/*low_4gb=*/ false,
@@ -2481,7 +2488,9 @@
art::ClassLinker* cl = runtime_->GetClassLinker();
if (data.GetSourceClassLoader() == nullptr) {
// AppendToBootClassPath includes dex file registration.
- cl->AppendToBootClassPath(&data.GetRedefinition().GetDexFile(), data.GetNewDexCache());
+ const art::DexFile& dex_file = data.GetRedefinition().GetDexFile();
+ runtime_->AppendToBootClassPath(
+ dex_file.GetLocation(), dex_file.GetLocation(), {{&dex_file, data.GetNewDexCache()}});
} else {
cl->RegisterExistingDexCache(data.GetNewDexCache(), data.GetSourceClassLoader());
}
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 1ac4756..eb97140 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -176,6 +176,7 @@
// Add boot class path dex files that were not included in the boot image.
// ClassLinker takes ownership of these dex files.
+ // DO NOT use directly. Use `Runtime::AddExtraBootDexFiles`.
void AddExtraBootDexFiles(Thread* self,
std::vector<std::unique_ptr<const DexFile>>&& additional_dex_files)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -780,10 +781,12 @@
REQUIRES_SHARED(Locks::mutator_lock_)
NO_THREAD_SAFETY_ANALYSIS;
+ // DO NOT use directly. Use `Runtime::AppendToBootClassPath`.
void AppendToBootClassPath(Thread* self, const DexFile* dex_file)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::dex_lock_);
+ // DO NOT use directly. Use `Runtime::AppendToBootClassPath`.
void AppendToBootClassPath(const DexFile* dex_file, ObjPtr<mirror::DexCache> dex_cache)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::dex_lock_);
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 390fcf0..6e583af 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -16,6 +16,8 @@
#include "runtime.h"
+#include <utility>
+
#ifdef __linux__
#include <sys/prctl.h>
#endif
@@ -3477,28 +3479,69 @@
return false;
}
+void Runtime::AppendToBootClassPath(const std::string& filename, const std::string& location) {
+ DCHECK(!DexFileLoader::IsMultiDexLocation(filename.c_str()));
+ boot_class_path_.push_back(filename);
+ if (!boot_class_path_locations_.empty()) {
+ DCHECK(!DexFileLoader::IsMultiDexLocation(location.c_str()));
+ boot_class_path_locations_.push_back(location);
+ }
+}
+
void Runtime::AppendToBootClassPath(
const std::string& filename,
const std::string& location,
const std::vector<std::unique_ptr<const art::DexFile>>& dex_files) {
- boot_class_path_.push_back(filename);
- if (!boot_class_path_locations_.empty()) {
- boot_class_path_locations_.push_back(location);
- }
+ AppendToBootClassPath(filename, location);
ScopedObjectAccess soa(Thread::Current());
for (const std::unique_ptr<const art::DexFile>& dex_file : dex_files) {
+ // The first element must not be at a multi-dex location, while other elements must be.
+ DCHECK_NE(DexFileLoader::IsMultiDexLocation(dex_file->GetLocation().c_str()),
+ dex_file.get() == dex_files.begin()->get());
GetClassLinker()->AppendToBootClassPath(Thread::Current(), dex_file.get());
}
}
+void Runtime::AppendToBootClassPath(const std::string& filename,
+ const std::string& location,
+ const std::vector<const art::DexFile*>& dex_files) {
+ AppendToBootClassPath(filename, location);
+ ScopedObjectAccess soa(Thread::Current());
+ for (const art::DexFile* dex_file : dex_files) {
+ // The first element must not be at a multi-dex location, while other elements must be.
+ DCHECK_NE(DexFileLoader::IsMultiDexLocation(dex_file->GetLocation().c_str()),
+ dex_file == *dex_files.begin());
+ GetClassLinker()->AppendToBootClassPath(Thread::Current(), dex_file);
+ }
+}
+
+void Runtime::AppendToBootClassPath(
+ const std::string& filename,
+ const std::string& location,
+ const std::vector<std::pair<const art::DexFile*, ObjPtr<mirror::DexCache>>>&
+ dex_files_and_cache) {
+ AppendToBootClassPath(filename, location);
+ ScopedObjectAccess soa(Thread::Current());
+ for (const auto& [dex_file, dex_cache] : dex_files_and_cache) {
+ // The first element must not be at a multi-dex location, while other elements must be.
+ DCHECK_NE(DexFileLoader::IsMultiDexLocation(dex_file->GetLocation().c_str()),
+ dex_file == dex_files_and_cache.begin()->first);
+ GetClassLinker()->AppendToBootClassPath(dex_file, dex_cache);
+ }
+}
+
void Runtime::AddExtraBootDexFiles(const std::string& filename,
const std::string& location,
std::vector<std::unique_ptr<const art::DexFile>>&& dex_files) {
- boot_class_path_.push_back(filename);
- if (!boot_class_path_locations_.empty()) {
- boot_class_path_locations_.push_back(location);
- }
+ AppendToBootClassPath(filename, location);
ScopedObjectAccess soa(Thread::Current());
+ if (kIsDebugBuild) {
+ for (const std::unique_ptr<const art::DexFile>& dex_file : dex_files) {
+ // The first element must not be at a multi-dex location, while other elements must be.
+ DCHECK_NE(DexFileLoader::IsMultiDexLocation(dex_file->GetLocation().c_str()),
+ dex_file.get() == dex_files.begin()->get());
+ }
+ }
GetClassLinker()->AddExtraBootDexFiles(Thread::Current(), std::move(dex_files));
}
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 395128d..a932718 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -302,11 +302,24 @@
return boot_class_path_locations_.empty() ? boot_class_path_ : boot_class_path_locations_;
}
- // Dynamically add an element to boot class path.
+ // Dynamically adds an element to boot class path.
void AppendToBootClassPath(const std::string& filename,
const std::string& location,
const std::vector<std::unique_ptr<const art::DexFile>>& dex_files);
+ // Same as above, but takes raw pointers.
+ void AppendToBootClassPath(const std::string& filename,
+ const std::string& location,
+ const std::vector<const art::DexFile*>& dex_files);
+
+ // Same as above, but also takes a dex cache for each dex file.
+ void AppendToBootClassPath(
+ const std::string& filename,
+ const std::string& location,
+ const std::vector<std::pair<const art::DexFile*, ObjPtr<mirror::DexCache>>>&
+ dex_files_and_cache);
+
+ // Dynamically adds an element to boot class path and takes ownership of the dex files.
void AddExtraBootDexFiles(const std::string& filename,
const std::string& location,
std::vector<std::unique_ptr<const art::DexFile>>&& dex_files);
@@ -1156,6 +1169,8 @@
// Caches the apex versions produced by `GetApexVersions`.
void InitializeApexVersions();
+ void AppendToBootClassPath(const std::string& filename, const std::string& location);
+
// A pointer to the active runtime or null.
static Runtime* instance_;