diff options
author | 2021-10-11 19:09:00 -0700 | |
---|---|---|
committer | 2021-10-26 17:36:32 +0000 | |
commit | 9c924e89e5f52da9faadd1e4e60c73eaed6bc9d1 (patch) | |
tree | 8ffdc7f0c144cb392b50144a9ae9cb4ac4d3cca7 | |
parent | d690f8ae8f8e2675bc52089a83ac18c749f8e6d2 (diff) |
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
-rw-r--r-- | runtime/class_linker.cc | 48 | ||||
-rw-r--r-- | runtime/class_linker.h | 25 | ||||
-rw-r--r-- | runtime/class_loader_context.cc | 133 | ||||
-rw-r--r-- | runtime/class_loader_context.h | 5 | ||||
-rw-r--r-- | runtime/class_loader_context_test.cc | 34 | ||||
-rw-r--r-- | runtime/common_runtime_test.cc | 18 | ||||
-rw-r--r-- | runtime/common_runtime_test.h | 9 | ||||
-rw-r--r-- | runtime/hidden_api_test.cc | 3 | ||||
-rw-r--r-- | runtime/well_known_classes.cc | 2 | ||||
-rw-r--r-- | runtime/well_known_classes.h | 1 |
10 files changed, 243 insertions, 35 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 0d50dd3bd5..4875298e68 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -2612,6 +2612,16 @@ bool ClassLinker::FindClassInSharedLibraries(ScopedObjectAccessAlreadyRunnable& /*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 @@ bool ClassLinker::FindClassInSharedLibraries(ScopedObjectAccessAlreadyRunnable& 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 @@ bool ClassLinker::FindClassInBaseDexClassLoader(ScopedObjectAccessAlreadyRunnabl 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 @@ bool ClassLinker::FindClassInBaseDexClassLoader(ScopedObjectAccessAlreadyRunnabl 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 @@ ObjPtr<mirror::ClassLoader> ClassLinker::CreateWellKnownClassLoader( 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 @@ ObjPtr<mirror::ClassLoader> ClassLinker::CreateWellKnownClassLoader( 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 @@ jobject ClassLinker::CreateWellKnownClassLoader(Thread* self, 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 @@ jobject ClassLinker::CreateWellKnownClassLoader(Thread* self, 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 @@ jobject ClassLinker::CreateWellKnownClassLoader(Thread* self, 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 8f334051ca..eaaf128527 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -665,7 +665,8 @@ class ClassLinker { 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 @@ class ClassLinker { 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 @@ class ClassLinker { 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 228b95028a..318d117e60 100644 --- a/runtime/class_loader_context.cc +++ b/runtime/class_loader_context.cc @@ -56,6 +56,7 @@ static constexpr char kClassLoaderClosingMark = ']'; 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 @@ static void AddToWorkList( 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::unique_ptr<ClassLoaderContext::ClassLoaderInfo> ClassLoaderContext::ParseCl 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 @@ std::unique_ptr<ClassLoaderContext::ClassLoaderInfo> ClassLoaderContext::ParseCl 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 @@ std::unique_ptr<ClassLoaderContext::ClassLoaderInfo> ClassLoaderContext::ParseCl (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 @@ std::unique_ptr<ClassLoaderContext::ClassLoaderInfo> ClassLoaderContext::ParseCl // 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 @@ std::unique_ptr<ClassLoaderContext::ClassLoaderInfo> ClassLoaderContext::ParseCl ++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 @@ void ClassLoaderContext::EncodeSharedLibAndParent(const ClassLoaderInfo& info, 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 @@ void ClassLoaderContext::EncodeSharedLibAndParent(const ClassLoaderInfo& info, (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 @@ static ObjPtr<mirror::ClassLoader> CreateClassLoaderInternal( } } - 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 @@ static ObjPtr<mirror::ClassLoader> CreateClassLoaderInternal( } } + 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 @@ static ObjPtr<mirror::ClassLoader> CreateClassLoaderInternal( 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 @@ bool ClassLoaderContext::CreateInfoFromClassLoader( 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 @@ bool ClassLoaderContext::CreateInfoFromClassLoader( 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 @@ bool ClassLoaderContext::CreateInfoFromClassLoader( 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 @@ bool ClassLoaderContext::CreateInfoFromClassLoader( 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 @@ bool ClassLoaderContext::CreateInfoFromClassLoader( // 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 @@ std::unique_ptr<ClassLoaderContext> ClassLoaderContext::CreateContextForClassLoa 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 33af16a225..eceea00177 100644 --- a/runtime/class_loader_context.h +++ b/runtime/class_loader_context.h @@ -225,6 +225,8 @@ class ClassLoaderContext { 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 @@ class ClassLoaderContext { 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 bf51ae3a0f..073b4b61e2 100644 --- a/runtime/class_loader_context_test.cc +++ b/runtime/class_loader_context_test.cc @@ -77,6 +77,15 @@ class ClassLoaderContextTest : public CommonRuntimeTest { 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 @@ class ClassLoaderContextTest : public CommonRuntimeTest { 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, ParseValidContextChain) { 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 b748e37917..4eb34083d1 100644 --- a/runtime/common_runtime_test.cc +++ b/runtime/common_runtime_test.cc @@ -255,7 +255,8 @@ jobject 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 @@ CommonRuntimeTestImpl::LoadDexInWellKnownClassLoader(const std::vector<std::stri class_path, loader_class, parent_loader, - shared_libraries); + shared_libraries, + shared_libraries_after); { // Verify we build the correct chain. @@ -301,19 +303,23 @@ CommonRuntimeTestImpl::LoadDexInWellKnownClassLoader(const std::vector<std::stri 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 d3995f0195..7c11fd8fc5 100644 --- a/runtime/common_runtime_test.h +++ b/runtime/common_runtime_test.h @@ -154,16 +154,19 @@ class CommonRuntimeTestImpl : public CommonArtTestImpl { 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 7cec10c173..f5cd15ef4f 100644 --- a/runtime/hidden_api_test.cc +++ b/runtime/hidden_api_test.cc @@ -82,7 +82,8 @@ static bool LoadDexFiles(const std::string& path, 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 8414aa40b4..645f3ad3db 100644 --- a/runtime/well_known_classes.cc +++ b/runtime/well_known_classes.cc @@ -132,6 +132,7 @@ jfieldID WellKnownClasses::dalvik_system_DexFile_cookie; 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 @@ void WellKnownClasses::InitFieldsAndMethodsOnly(JNIEnv* env) { 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 434d041c9f..7da085f825 100644 --- a/runtime/well_known_classes.h +++ b/runtime/well_known_classes.h @@ -143,6 +143,7 @@ struct WellKnownClasses { 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; |