Add support to place shared libraries after the dex path
This allows for a shared library to overriden by content in the dex path
Bug: 179429740
Test: m test-art-host-gtest-art_runtime_tests32
Change-Id: I5f69c7bf32b7bd389eff8bdbb21616ba89ed9e87
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 0d50dd3..4875298 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -2612,6 +2612,16 @@
/*out*/ ObjPtr<mirror::Class>* result) {
ArtField* field =
jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_sharedLibraryLoaders);
+ return FindClassInSharedLibrariesHelper(soa, self, descriptor, hash, class_loader, field, result);
+}
+
+bool ClassLinker::FindClassInSharedLibrariesHelper(ScopedObjectAccessAlreadyRunnable& soa,
+ Thread* self,
+ const char* descriptor,
+ size_t hash,
+ Handle<mirror::ClassLoader> class_loader,
+ ArtField* field,
+ /*out*/ ObjPtr<mirror::Class>* result) {
ObjPtr<mirror::Object> raw_shared_libraries = field->GetObject(class_loader.Get());
if (raw_shared_libraries == nullptr) {
return true;
@@ -2631,6 +2641,17 @@
return true;
}
+bool ClassLinker::FindClassInSharedLibrariesAfter(ScopedObjectAccessAlreadyRunnable& soa,
+ Thread* self,
+ const char* descriptor,
+ size_t hash,
+ Handle<mirror::ClassLoader> class_loader,
+ /*out*/ ObjPtr<mirror::Class>* result) {
+ ArtField* field = jni::DecodeArtField(
+ WellKnownClasses::dalvik_system_BaseDexClassLoader_sharedLibraryLoadersAfter);
+ return FindClassInSharedLibrariesHelper(soa, self, descriptor, hash, class_loader, field, result);
+}
+
bool ClassLinker::FindClassInBaseDexClassLoader(ScopedObjectAccessAlreadyRunnable& soa,
Thread* self,
const char* descriptor,
@@ -2665,6 +2686,10 @@
FindClassInBaseDexClassLoaderClassPath(soa, descriptor, hash, class_loader, result),
*result,
self);
+ RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION(
+ FindClassInSharedLibrariesAfter(soa, self, descriptor, hash, class_loader, result),
+ *result,
+ self);
// We did not find a class, but the class loader chain was recognized, so we
// return true.
return true;
@@ -2686,6 +2711,10 @@
FindClassInBaseDexClassLoaderClassPath(soa, descriptor, hash, class_loader, result),
*result,
self);
+ RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION(
+ FindClassInSharedLibrariesAfter(soa, self, descriptor, hash, class_loader, result),
+ *result,
+ self);
// Create a handle as RegisterDexFile may allocate dex caches (and cause thread suspension).
StackHandleScope<1> hs(self);
@@ -9839,7 +9868,8 @@
const std::vector<const DexFile*>& dex_files,
Handle<mirror::Class> loader_class,
Handle<mirror::ClassLoader> parent_loader,
- Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries) {
+ Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries,
+ Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries_after) {
StackHandleScope<5> hs(self);
@@ -9959,6 +9989,12 @@
DCHECK(shared_libraries_field != nullptr);
shared_libraries_field->SetObject<false>(h_class_loader.Get(), shared_libraries.Get());
+ ArtField* shared_libraries_after_field =
+ jni::DecodeArtField(
+ WellKnownClasses::dalvik_system_BaseDexClassLoader_sharedLibraryLoadersAfter);
+ DCHECK(shared_libraries_after_field != nullptr);
+ shared_libraries_after_field->SetObject<false>(h_class_loader.Get(),
+ shared_libraries_after.Get());
return h_class_loader.Get();
}
@@ -9966,7 +10002,8 @@
const std::vector<const DexFile*>& dex_files,
jclass loader_class,
jobject parent_loader,
- jobject shared_libraries) {
+ jobject shared_libraries,
+ jobject shared_libraries_after) {
CHECK(self->GetJniEnv()->IsSameObject(loader_class,
WellKnownClasses::dalvik_system_PathClassLoader) ||
self->GetJniEnv()->IsSameObject(loader_class,
@@ -9979,7 +10016,7 @@
ScopedObjectAccessUnchecked soa(self);
// For now, create a libcore-level DexFile for each ART DexFile. This "explodes" multidex.
- StackHandleScope<4> hs(self);
+ StackHandleScope<5> hs(self);
Handle<mirror::Class> h_loader_class =
hs.NewHandle<mirror::Class>(soa.Decode<mirror::Class>(loader_class));
@@ -9987,13 +10024,16 @@
hs.NewHandle<mirror::ClassLoader>(soa.Decode<mirror::ClassLoader>(parent_loader));
Handle<mirror::ObjectArray<mirror::ClassLoader>> h_shared_libraries =
hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::ClassLoader>>(shared_libraries));
+ Handle<mirror::ObjectArray<mirror::ClassLoader>> h_shared_libraries_after =
+ hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::ClassLoader>>(shared_libraries_after));
ObjPtr<mirror::ClassLoader> loader = CreateWellKnownClassLoader(
self,
dex_files,
h_loader_class,
h_parent,
- h_shared_libraries);
+ h_shared_libraries,
+ h_shared_libraries_after);
// Make it a global ref and return.
ScopedLocalRef<jobject> local_ref(
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 8f33405..eaaf128 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -665,7 +665,8 @@
const std::vector<const DexFile*>& dex_files,
jclass loader_class,
jobject parent_loader,
- jobject shared_libraries = nullptr)
+ jobject shared_libraries = nullptr,
+ jobject shared_libraries_after = nullptr)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::dex_lock_);
@@ -683,7 +684,8 @@
const std::vector<const DexFile*>& dex_files,
Handle<mirror::Class> loader_class,
Handle<mirror::ClassLoader> parent_loader,
- Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries)
+ Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries,
+ Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries_after)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::dex_lock_);
@@ -1015,6 +1017,25 @@
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::dex_lock_);
+ bool FindClassInSharedLibrariesHelper(ScopedObjectAccessAlreadyRunnable& soa,
+ Thread* self,
+ const char* descriptor,
+ size_t hash,
+ Handle<mirror::ClassLoader> class_loader,
+ ArtField* field,
+ /*out*/ ObjPtr<mirror::Class>* result)
+ REQUIRES_SHARED(Locks::mutator_lock_)
+ REQUIRES(!Locks::dex_lock_);
+
+ bool FindClassInSharedLibrariesAfter(ScopedObjectAccessAlreadyRunnable& soa,
+ Thread* self,
+ const char* descriptor,
+ size_t hash,
+ Handle<mirror::ClassLoader> class_loader,
+ /*out*/ ObjPtr<mirror::Class>* result)
+ REQUIRES_SHARED(Locks::mutator_lock_)
+ REQUIRES(!Locks::dex_lock_);
+
// Finds the class in the classpath of the given class loader. It only searches the class loader
// dex files and does not recurse into its parent.
// The method checks that the provided class loader is either a PathClassLoader or a
diff --git a/runtime/class_loader_context.cc b/runtime/class_loader_context.cc
index 228b950..318d117 100644
--- a/runtime/class_loader_context.cc
+++ b/runtime/class_loader_context.cc
@@ -56,6 +56,7 @@
static constexpr char kClassLoaderSharedLibraryOpeningMark = '{';
static constexpr char kClassLoaderSharedLibraryClosingMark = '}';
static constexpr char kClassLoaderSharedLibrarySeparator = '#';
+static constexpr char kClassLoaderSharedLibraryAfterSeparator = '~';
static constexpr char kClassLoaderSeparator = ';';
static constexpr char kClasspathSeparator = ':';
static constexpr char kDexFileChecksumSeparator = '*';
@@ -80,6 +81,9 @@
for (size_t i = 0; i < info->shared_libraries.size(); ++i) {
work_list.push_back(info->shared_libraries[i].get());
}
+ for (size_t i = 0; i < info->shared_libraries_after.size(); ++i) {
+ work_list.push_back(info->shared_libraries_after[i].get());
+ }
}
ClassLoaderContext::~ClassLoaderContext() {
@@ -239,6 +243,7 @@
std::vector<std::string> shared_libraries;
size_t cursor = 0;
while (cursor != shared_libraries_spec.length()) {
+ bool is_after = false;
size_t shared_library_separator =
shared_libraries_spec.find_first_of(kClassLoaderSharedLibrarySeparator, cursor);
size_t shared_library_open =
@@ -247,6 +252,12 @@
if (shared_library_separator == std::string::npos) {
// Only one shared library, for example:
// PCL[...]
+ if (shared_libraries_spec[cursor] == kClassLoaderSharedLibraryAfterSeparator) {
+ // This library was marked to be loaded after the dex path
+ is_after = true;
+ // Pass the shared library after separator marker.
+ ++cursor;
+ }
shared_library_spec =
shared_libraries_spec.substr(cursor, shared_libraries_spec.length() - cursor);
cursor = shared_libraries_spec.length();
@@ -254,6 +265,12 @@
(shared_library_open > shared_library_separator)) {
// We found a shared library without nested shared libraries, for example:
// PCL[...]#PCL[...]{...}
+ if (shared_libraries_spec[cursor] == kClassLoaderSharedLibraryAfterSeparator) {
+ // This library was marked to be loaded after the dex path
+ is_after = true;
+ // Pass the shared library after separator marker.
+ ++cursor;
+ }
shared_library_spec =
shared_libraries_spec.substr(cursor, shared_library_separator - cursor);
cursor = shared_library_separator + 1;
@@ -266,6 +283,12 @@
// No matching closing marker, return an error.
return nullptr;
}
+ if (shared_libraries_spec[cursor] == kClassLoaderSharedLibraryAfterSeparator) {
+ // This library was marked to be loaded after the dex path
+ is_after = true;
+ // Pass the shared library after separator marker.
+ ++cursor;
+ }
shared_library_spec = shared_libraries_spec.substr(cursor, closing_marker + 1 - cursor);
cursor = closing_marker + 1;
if (cursor != shared_libraries_spec.length() &&
@@ -274,12 +297,17 @@
++cursor;
}
}
- std::unique_ptr<ClassLoaderInfo> shared_library(
- ParseInternal(shared_library_spec, parse_checksums));
- if (shared_library == nullptr) {
+
+ std::unique_ptr<ClassLoaderInfo> shared_library_info(
+ ParseInternal(shared_library_spec, parse_checksums));
+ if (shared_library_info == nullptr) {
return nullptr;
}
- info->shared_libraries.push_back(std::move(shared_library));
+ if (is_after) {
+ info->shared_libraries_after.push_back(std::move(shared_library_info));
+ } else {
+ info->shared_libraries.push_back(std::move(shared_library_info));
+ }
}
}
@@ -709,7 +737,7 @@
bool for_dex2oat,
ClassLoaderInfo* stored_info,
std::ostringstream& out) const {
- if (!info.shared_libraries.empty()) {
+ if (!info.shared_libraries.empty() || !info.shared_libraries_after.empty()) {
out << kClassLoaderSharedLibraryOpeningMark;
for (uint32_t i = 0; i < info.shared_libraries.size(); ++i) {
if (i > 0) {
@@ -722,6 +750,20 @@
(stored_info == nullptr ? nullptr : stored_info->shared_libraries[i].get()),
out);
}
+
+ for (uint32_t i = 0; i < info.shared_libraries_after.size(); ++i) {
+ if (i > 0 || !info.shared_libraries.empty()) {
+ out << kClassLoaderSharedLibrarySeparator;
+ }
+ out << kClassLoaderSharedLibraryAfterSeparator;
+ EncodeContextInternal(
+ *info.shared_libraries_after[i].get(),
+ base_dir,
+ for_dex2oat,
+ (stored_info == nullptr ? nullptr : stored_info->shared_libraries_after[i].get()),
+ out);
+ }
+
out << kClassLoaderSharedLibraryClosingMark;
}
if (info.parent != nullptr) {
@@ -772,9 +814,11 @@
}
}
- StackHandleScope<3> hs(self);
+ StackHandleScope<4> hs(self);
MutableHandle<mirror::ObjectArray<mirror::ClassLoader>> libraries(
hs.NewHandle<mirror::ObjectArray<mirror::ClassLoader>>(nullptr));
+ MutableHandle<mirror::ObjectArray<mirror::ClassLoader>> libraries_after(
+ hs.NewHandle<mirror::ObjectArray<mirror::ClassLoader>>(nullptr));
if (!info.shared_libraries.empty()) {
libraries.Assign(mirror::ObjectArray<mirror::ClassLoader>::Alloc(
@@ -796,6 +840,26 @@
}
}
+ if (!info.shared_libraries_after.empty()) {
+ libraries_after.Assign(mirror::ObjectArray<mirror::ClassLoader>::Alloc(
+ self,
+ GetClassRoot<mirror::ObjectArray<mirror::ClassLoader>>(),
+ info.shared_libraries_after.size()));
+ for (uint32_t i = 0; i < info.shared_libraries_after.size(); ++i) {
+ // We should only add the compilation sources to the first class loader.
+ libraries_after->Set(i,
+ CreateClassLoaderInternal(
+ self,
+ soa,
+ *info.shared_libraries_after[i].get(),
+ /* for_shared_library= */ true,
+ map_scope,
+ canonicalized_libraries,
+ /* add_compilation_sources= */ false,
+ compilation_sources));
+ }
+ }
+
MutableHandle<mirror::ClassLoader> parent = hs.NewHandle<mirror::ClassLoader>(nullptr);
if (info.parent != nullptr) {
// We should only add the compilation sources to the first class loader.
@@ -827,7 +891,8 @@
class_path_files,
loader_class,
parent,
- libraries);
+ libraries,
+ libraries_after);
if (for_shared_library) {
canonicalized_libraries[FlattenClasspath(info.classpath)] =
map_scope.NewHandle<mirror::ClassLoader>(loader);
@@ -1063,7 +1128,8 @@
Handle<mirror::ClassLoader> class_loader,
Handle<mirror::ObjectArray<mirror::Object>> dex_elements,
ClassLoaderInfo* child_info,
- bool is_shared_library)
+ bool is_shared_library,
+ bool is_after)
REQUIRES_SHARED(Locks::mutator_lock_) {
if (ClassLinker::IsBootClassLoader(soa, class_loader.Get())) {
// Nothing to do for the boot class loader as we don't add its dex files to the context.
@@ -1105,7 +1171,11 @@
if (child_info == nullptr) {
class_loader_chain_.reset(info);
} else if (is_shared_library) {
- child_info->shared_libraries.push_back(std::unique_ptr<ClassLoaderInfo>(info));
+ if (is_after) {
+ child_info->shared_libraries_after.push_back(std::unique_ptr<ClassLoaderInfo>(info));
+ } else {
+ child_info->shared_libraries.push_back(std::unique_ptr<ClassLoaderInfo>(info));
+ }
} else {
child_info->parent.reset(info);
}
@@ -1126,7 +1196,7 @@
ScopedNullHandle<mirror::ObjectArray<mirror::Object>> null_dex_elements;
// Add the shared libraries.
- StackHandleScope<3> hs(Thread::Current());
+ StackHandleScope<5> hs(Thread::Current());
ArtField* field =
jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_sharedLibraryLoaders);
ObjPtr<mirror::Object> raw_shared_libraries = field->GetObject(class_loader.Get());
@@ -1136,8 +1206,31 @@
MutableHandle<mirror::ClassLoader> temp_loader = hs.NewHandle<mirror::ClassLoader>(nullptr);
for (auto library : shared_libraries.Iterate<mirror::ClassLoader>()) {
temp_loader.Assign(library);
- if (!CreateInfoFromClassLoader(
- soa, temp_loader, null_dex_elements, info, /*is_shared_library=*/ true)) {
+ if (!CreateInfoFromClassLoader(soa,
+ temp_loader,
+ null_dex_elements,
+ info,
+ /*is_shared_library=*/ true,
+ /*is_after=*/ false)) {
+ return false;
+ }
+ }
+ }
+ ArtField* field2 = jni::DecodeArtField(
+ WellKnownClasses::dalvik_system_BaseDexClassLoader_sharedLibraryLoadersAfter);
+ ObjPtr<mirror::Object> raw_shared_libraries_after = field2->GetObject(class_loader.Get());
+ if (raw_shared_libraries_after != nullptr) {
+ Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries_after =
+ hs.NewHandle(raw_shared_libraries_after->AsObjectArray<mirror::ClassLoader>());
+ MutableHandle<mirror::ClassLoader> temp_loader = hs.NewHandle<mirror::ClassLoader>(nullptr);
+ for (auto library : shared_libraries_after.Iterate<mirror::ClassLoader>()) {
+ temp_loader.Assign(library);
+ if (!CreateInfoFromClassLoader(soa,
+ temp_loader,
+ null_dex_elements,
+ info,
+ /*is_shared_library=*/ true,
+ /*is_after=*/ true)) {
return false;
}
}
@@ -1145,8 +1238,12 @@
// We created the ClassLoaderInfo for the current loader. Move on to its parent.
Handle<mirror::ClassLoader> parent = hs.NewHandle(class_loader->GetParent());
- if (!CreateInfoFromClassLoader(
- soa, parent, null_dex_elements, info, /*is_shared_library=*/ false)) {
+ if (!CreateInfoFromClassLoader(soa,
+ parent,
+ null_dex_elements,
+ info,
+ /*is_shared_library=*/ false,
+ /*is_after=*/ false)) {
return false;
}
return true;
@@ -1167,8 +1264,12 @@
Handle<mirror::ObjectArray<mirror::Object>> h_dex_elements =
hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Object>>(dex_elements));
std::unique_ptr<ClassLoaderContext> result(new ClassLoaderContext(/*owns_the_dex_files=*/ false));
- if (!result->CreateInfoFromClassLoader(
- soa, h_class_loader, h_dex_elements, nullptr, /*is_shared_library=*/ false)) {
+ if (!result->CreateInfoFromClassLoader(soa,
+ h_class_loader,
+ h_dex_elements,
+ nullptr,
+ /*is_shared_library=*/ false,
+ /*is_after=*/ false)) {
return nullptr;
}
return result;
diff --git a/runtime/class_loader_context.h b/runtime/class_loader_context.h
index 33af16a..eceea00 100644
--- a/runtime/class_loader_context.h
+++ b/runtime/class_loader_context.h
@@ -225,6 +225,8 @@
ClassLoaderType type;
// Shared libraries this context has.
std::vector<std::unique_ptr<ClassLoaderInfo>> shared_libraries;
+ // Shared libraries that will be loaded after apks code that this context has.
+ std::vector<std::unique_ptr<ClassLoaderInfo>> shared_libraries_after;
// The list of class path elements that this loader loads.
// Note that this list may contain relative paths.
std::vector<std::string> classpath;
@@ -297,7 +299,8 @@
Handle<mirror::ClassLoader> class_loader,
Handle<mirror::ObjectArray<mirror::Object>> dex_elements,
ClassLoaderInfo* child_info,
- bool is_shared_library)
+ bool is_shared_library,
+ bool is_after)
REQUIRES_SHARED(Locks::mutator_lock_);
// Encodes the context as a string suitable to be passed to dex2oat or to be added to the
diff --git a/runtime/class_loader_context_test.cc b/runtime/class_loader_context_test.cc
index bf51ae3..073b4b6 100644
--- a/runtime/class_loader_context_test.cc
+++ b/runtime/class_loader_context_test.cc
@@ -77,6 +77,15 @@
classpath);
}
+ void VerifyClassLoaderSharedLibraryPCLAfter(ClassLoaderContext* context,
+ size_t loader_index,
+ size_t shared_library_index,
+ const std::string& classpath) {
+ VerifyClassLoaderInfoSLAfter(
+ context, loader_index, shared_library_index, ClassLoaderContext::kPathClassLoader,
+ classpath);
+ }
+
void VerifyClassLoaderSharedLibraryIMC(ClassLoaderContext* context,
size_t loader_index,
size_t shared_library_index,
@@ -356,7 +365,25 @@
ASSERT_GT(info.shared_libraries.size(), shared_library_index);
const ClassLoaderContext::ClassLoaderInfo& sl =
*info.shared_libraries[shared_library_index].get();
- ASSERT_EQ(type, info.type);
+ ASSERT_EQ(type, sl.type);
+ std::vector<std::string> expected_classpath;
+ Split(classpath, ':', &expected_classpath);
+ ASSERT_EQ(expected_classpath, sl.classpath);
+ }
+
+ void VerifyClassLoaderInfoSLAfter(ClassLoaderContext* context,
+ size_t loader_index,
+ size_t shared_library_index,
+ ClassLoaderContext::ClassLoaderType type,
+ const std::string& classpath) {
+ ASSERT_TRUE(context != nullptr);
+ ASSERT_GT(context->GetParentChainSize(), loader_index);
+ const ClassLoaderContext::ClassLoaderInfo& info = *context->GetParent(loader_index);
+ ASSERT_GT(info.shared_libraries_after.size(), shared_library_index);
+
+ const ClassLoaderContext::ClassLoaderInfo& sl =
+ *info.shared_libraries_after[shared_library_index].get();
+ ASSERT_EQ(type, sl.type);
std::vector<std::string> expected_classpath;
Split(classpath, ':', &expected_classpath);
ASSERT_EQ(expected_classpath, sl.classpath);
@@ -437,10 +464,13 @@
TEST_F(ClassLoaderContextTest, ParseSharedLibraries) {
std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(
- "PCL[a.dex:b.dex]{PCL[s1.dex]#PCL[s2.dex:s3.dex]};DLC[c.dex:d.dex]{DLC[s4.dex]}");
+ "PCL[a.dex:b.dex]{PCL[s1.dex]#PCL[s2.dex:s3.dex]#~PCL[s5.dex]#~PCL[s6.dex:s7.dex]};"
+ "DLC[c.dex:d.dex]{DLC[s4.dex]}");
VerifyContextSize(context.get(), 2);
VerifyClassLoaderSharedLibraryPCL(context.get(), 0, 0, "s1.dex");
VerifyClassLoaderSharedLibraryPCL(context.get(), 0, 1, "s2.dex:s3.dex");
+ VerifyClassLoaderSharedLibraryPCLAfter(context.get(), 0, 0, "s5.dex");
+ VerifyClassLoaderSharedLibraryPCLAfter(context.get(), 0, 1, "s6.dex:s7.dex");
VerifyClassLoaderDLC(context.get(), 1, "c.dex:d.dex");
VerifyClassLoaderSharedLibraryDLC(context.get(), 1, 0, "s4.dex");
}
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index b748e37..4eb3408 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -255,7 +255,8 @@
CommonRuntimeTestImpl::LoadDexInWellKnownClassLoader(const std::vector<std::string>& dex_names,
jclass loader_class,
jobject parent_loader,
- jobject shared_libraries) {
+ jobject shared_libraries,
+ jobject shared_libraries_after) {
std::vector<const DexFile*> class_path;
for (const std::string& dex_name : dex_names) {
std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles(dex_name.c_str());
@@ -273,7 +274,8 @@
class_path,
loader_class,
parent_loader,
- shared_libraries);
+ shared_libraries,
+ shared_libraries_after);
{
// Verify we build the correct chain.
@@ -301,19 +303,23 @@
jobject CommonRuntimeTestImpl::LoadDexInPathClassLoader(const std::string& dex_name,
jobject parent_loader,
- jobject shared_libraries) {
+ jobject shared_libraries,
+ jobject shared_libraries_after) {
return LoadDexInPathClassLoader(std::vector<std::string>{ dex_name },
parent_loader,
- shared_libraries);
+ shared_libraries,
+ shared_libraries_after);
}
jobject CommonRuntimeTestImpl::LoadDexInPathClassLoader(const std::vector<std::string>& names,
jobject parent_loader,
- jobject shared_libraries) {
+ jobject shared_libraries,
+ jobject shared_libraries_after) {
return LoadDexInWellKnownClassLoader(names,
WellKnownClasses::dalvik_system_PathClassLoader,
parent_loader,
- shared_libraries);
+ shared_libraries,
+ shared_libraries_after);
}
jobject CommonRuntimeTestImpl::LoadDexInDelegateLastClassLoader(const std::string& dex_name,
diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h
index d3995f0..7c11fd8 100644
--- a/runtime/common_runtime_test.h
+++ b/runtime/common_runtime_test.h
@@ -154,16 +154,19 @@
jobject LoadDexInPathClassLoader(const std::string& dex_name,
jobject parent_loader,
- jobject shared_libraries = nullptr);
+ jobject shared_libraries = nullptr,
+ jobject shared_libraries_after = nullptr);
jobject LoadDexInPathClassLoader(const std::vector<std::string>& dex_names,
jobject parent_loader,
- jobject shared_libraries = nullptr);
+ jobject shared_libraries = nullptr,
+ jobject shared_libraries_after = nullptr);
jobject LoadDexInDelegateLastClassLoader(const std::string& dex_name, jobject parent_loader);
jobject LoadDexInInMemoryDexClassLoader(const std::string& dex_name, jobject parent_loader);
jobject LoadDexInWellKnownClassLoader(const std::vector<std::string>& dex_names,
jclass loader_class,
jobject parent_loader,
- jobject shared_libraries = nullptr);
+ jobject shared_libraries = nullptr,
+ jobject shared_libraries_after = nullptr);
void VisitDexes(ArrayRef<const std::string> dexes,
const std::function<void(MethodReference)>& method_visitor,
diff --git a/runtime/hidden_api_test.cc b/runtime/hidden_api_test.cc
index 7cec10c..f5cd15e 100644
--- a/runtime/hidden_api_test.cc
+++ b/runtime/hidden_api_test.cc
@@ -82,7 +82,8 @@
MakeNonOwningPointerVector(*dex_files),
h_class,
/* parent_loader= */ ScopedNullHandle<mirror::ClassLoader>(),
- /* shared_libraries= */ ScopedNullHandle<mirror::ObjectArray<mirror::ClassLoader>>()));
+ /* shared_libraries= */ ScopedNullHandle<mirror::ObjectArray<mirror::ClassLoader>>(),
+ /* shared_libraries_after= */ ScopedNullHandle<mirror::ObjectArray<mirror::ClassLoader>>()));
for (const auto& dex_file : *dex_files) {
linker->RegisterDexFile(*dex_file.get(), h_loader.Get());
}
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index 8414aa4..645f3ad 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -132,6 +132,7 @@
jfieldID WellKnownClasses::dalvik_system_DexFile_fileName;
jfieldID WellKnownClasses::dalvik_system_BaseDexClassLoader_pathList;
jfieldID WellKnownClasses::dalvik_system_BaseDexClassLoader_sharedLibraryLoaders;
+jfieldID WellKnownClasses::dalvik_system_BaseDexClassLoader_sharedLibraryLoadersAfter;
jfieldID WellKnownClasses::dalvik_system_DexPathList_dexElements;
jfieldID WellKnownClasses::dalvik_system_DexPathList__Element_dexFile;
jfieldID WellKnownClasses::dalvik_system_VMRuntime_nonSdkApiUsageConsumer;
@@ -421,6 +422,7 @@
dalvik_system_BaseDexClassLoader_pathList = CacheField(env, dalvik_system_BaseDexClassLoader, false, "pathList", "Ldalvik/system/DexPathList;");
dalvik_system_BaseDexClassLoader_sharedLibraryLoaders = CacheField(env, dalvik_system_BaseDexClassLoader, false, "sharedLibraryLoaders", "[Ljava/lang/ClassLoader;");
+ dalvik_system_BaseDexClassLoader_sharedLibraryLoadersAfter = CacheField(env, dalvik_system_BaseDexClassLoader, false, "sharedLibraryLoadersAfter", "[Ljava/lang/ClassLoader;");
dalvik_system_DexFile_cookie = CacheField(env, dalvik_system_DexFile, false, "mCookie", "Ljava/lang/Object;");
dalvik_system_DexFile_fileName = CacheField(env, dalvik_system_DexFile, false, "mFileName", "Ljava/lang/String;");
dalvik_system_DexPathList_dexElements = CacheField(env, dalvik_system_DexPathList, false, "dexElements", "[Ldalvik/system/DexPathList$Element;");
diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h
index 434d041..7da085f 100644
--- a/runtime/well_known_classes.h
+++ b/runtime/well_known_classes.h
@@ -143,6 +143,7 @@
static jfieldID dalvik_system_BaseDexClassLoader_pathList;
static jfieldID dalvik_system_BaseDexClassLoader_sharedLibraryLoaders;
+ static jfieldID dalvik_system_BaseDexClassLoader_sharedLibraryLoadersAfter;
static jfieldID dalvik_system_DexFile_cookie;
static jfieldID dalvik_system_DexFile_fileName;
static jfieldID dalvik_system_DexPathList_dexElements;