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(