diff options
-rw-r--r-- | runtime/class_linker.cc | 24 | ||||
-rw-r--r-- | runtime/class_linker.h | 7 | ||||
-rw-r--r-- | runtime/class_loader_context.cc | 69 | ||||
-rw-r--r-- | runtime/class_loader_context.h | 9 | ||||
-rw-r--r-- | runtime/class_loader_context_test.cc | 28 | ||||
-rw-r--r-- | runtime/common_runtime_test.cc | 12 | ||||
-rw-r--r-- | runtime/common_runtime_test.h | 7 |
7 files changed, 103 insertions, 53 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 991faa27d3..9b2e1a10e4 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -9116,8 +9116,8 @@ ObjPtr<mirror::ClassLoader> ClassLinker::CreateWellKnownClassLoader( Thread* self, const std::vector<const DexFile*>& dex_files, Handle<mirror::Class> loader_class, - Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries, - Handle<mirror::ClassLoader> parent_loader) { + Handle<mirror::ClassLoader> parent_loader, + Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries) { StackHandleScope<5> hs(self); @@ -9246,7 +9246,8 @@ ObjPtr<mirror::ClassLoader> ClassLinker::CreateWellKnownClassLoader( jobject ClassLinker::CreateWellKnownClassLoader(Thread* self, const std::vector<const DexFile*>& dex_files, jclass loader_class, - jobject parent_loader) { + jobject parent_loader, + jobject shared_libraries) { CHECK(self->GetJniEnv()->IsSameObject(loader_class, WellKnownClasses::dalvik_system_PathClassLoader) || self->GetJniEnv()->IsSameObject(loader_class, @@ -9257,24 +9258,21 @@ jobject ClassLinker::CreateWellKnownClassLoader(Thread* self, ScopedObjectAccessUnchecked soa(self); // For now, create a libcore-level DexFile for each ART DexFile. This "explodes" multidex. - StackHandleScope<3> hs(self); + StackHandleScope<4> hs(self); Handle<mirror::Class> h_loader_class = hs.NewHandle<mirror::Class>(soa.Decode<mirror::Class>(loader_class)); - Handle<mirror::ClassLoader> parent = - hs.NewHandle<mirror::ClassLoader>(ObjPtr<mirror::ClassLoader>::DownCast( - (parent_loader != nullptr) - ? soa.Decode<mirror::ClassLoader>(parent_loader) - : nullptr)); - Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries = - hs.NewHandle<mirror::ObjectArray<mirror::ClassLoader>>(nullptr); + Handle<mirror::ClassLoader> h_parent = + 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)); ObjPtr<mirror::ClassLoader> loader = CreateWellKnownClassLoader( self, dex_files, h_loader_class, - shared_libraries, - parent); + h_parent, + h_shared_libraries); // Make it a global ref and return. ScopedLocalRef<jobject> local_ref( diff --git a/runtime/class_linker.h b/runtime/class_linker.h index 15a7204dd2..dd5f911330 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -574,7 +574,8 @@ class ClassLinker { jobject CreateWellKnownClassLoader(Thread* self, const std::vector<const DexFile*>& dex_files, jclass loader_class, - jobject parent_loader) + jobject parent_loader, + jobject shared_libraries = nullptr) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::dex_lock_); @@ -591,8 +592,8 @@ class ClassLinker { Thread* self, const std::vector<const DexFile*>& dex_files, Handle<mirror::Class> loader_class, - Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries, - Handle<mirror::ClassLoader> parent_loader) + Handle<mirror::ClassLoader> parent_loader, + Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::dex_lock_); diff --git a/runtime/class_loader_context.cc b/runtime/class_loader_context.cc index 029db7e5c7..2306ec950d 100644 --- a/runtime/class_loader_context.cc +++ b/runtime/class_loader_context.cc @@ -695,8 +695,8 @@ static ObjPtr<mirror::ClassLoader> CreateClassLoaderInternal( self, class_path_files, loader_class, - libraries, - parent); + parent, + libraries); if (for_shared_library) { canonicalized_libraries[FlattenClasspath(info.classpath)] = map_scope.NewHandle<mirror::ClassLoader>(loader); @@ -914,10 +914,11 @@ static bool GetDexFilesFromDexElementsArray( // the classpath. // This method is recursive (w.r.t. the class loader parent) and will stop once it reaches the // BootClassLoader. Note that the class loader chain is expected to be short. -bool ClassLoaderContext::AddInfoToContextFromClassLoader( +bool ClassLoaderContext::CreateInfoFromClassLoader( ScopedObjectAccessAlreadyRunnable& soa, Handle<mirror::ClassLoader> class_loader, - Handle<mirror::ObjectArray<mirror::Object>> dex_elements) + Handle<mirror::ObjectArray<mirror::Object>> dex_elements, + std::unique_ptr<ClassLoaderInfo>* return_info) 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. @@ -951,32 +952,45 @@ bool ClassLoaderContext::AddInfoToContextFromClassLoader( GetDexFilesFromDexElementsArray(soa, dex_elements, &dex_files_loaded); } - ClassLoaderInfo* info = new ClassLoaderContext::ClassLoaderInfo(type); - if (class_loader_chain_ == nullptr) { - class_loader_chain_.reset(info); - } else { - ClassLoaderInfo* child = class_loader_chain_.get(); - while (child->parent != nullptr) { - child = child->parent.get(); - } - child->parent.reset(info); - } - + std::unique_ptr<ClassLoaderInfo> info(new ClassLoaderContext::ClassLoaderInfo(type)); for (const DexFile* dex_file : dex_files_loaded) { info->classpath.push_back(dex_file->GetLocation()); info->checksums.push_back(dex_file->GetLocationChecksum()); info->opened_dex_files.emplace_back(dex_file); } - // We created the ClassLoaderInfo for the current loader. Move on to its parent. - - StackHandleScope<1> hs(Thread::Current()); - Handle<mirror::ClassLoader> parent = hs.NewHandle(class_loader->GetParent()); - // Note that dex_elements array is null here. The elements are considered to be part of the // current class loader and are not passed to the parents. ScopedNullHandle<mirror::ObjectArray<mirror::Object>> null_dex_elements; - return AddInfoToContextFromClassLoader(soa, parent, null_dex_elements); + + // Add the shared libraries. + StackHandleScope<3> hs(Thread::Current()); + ArtField* field = + jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_sharedLibraryLoaders); + ObjPtr<mirror::Object> raw_shared_libraries = field->GetObject(class_loader.Get()); + if (raw_shared_libraries != nullptr) { + Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries = + hs.NewHandle(raw_shared_libraries->AsObjectArray<mirror::ClassLoader>()); + MutableHandle<mirror::ClassLoader> temp_loader = hs.NewHandle<mirror::ClassLoader>(nullptr); + for (int32_t i = 0; i < shared_libraries->GetLength(); ++i) { + temp_loader.Assign(shared_libraries->Get(i)); + std::unique_ptr<ClassLoaderInfo> result; + if (!CreateInfoFromClassLoader(soa, temp_loader, null_dex_elements, &result)) { + return false; + } + info->shared_libraries.push_back(std::move(result)); + } + } + + // We created the ClassLoaderInfo for the current loader. Move on to its parent. + Handle<mirror::ClassLoader> parent = hs.NewHandle(class_loader->GetParent()); + std::unique_ptr<ClassLoaderInfo> parent_info; + if (!CreateInfoFromClassLoader(soa, parent, null_dex_elements, &parent_info)) { + return false; + } + info->parent = std::move(parent_info); + *return_info = std::move(info); + return true; } std::unique_ptr<ClassLoaderContext> ClassLoaderContext::CreateContextForClassLoader( @@ -991,12 +1005,13 @@ 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->AddInfoToContextFromClassLoader(soa, h_class_loader, h_dex_elements)) { - return result; - } else { + std::unique_ptr<ClassLoaderInfo> info; + if (!CreateInfoFromClassLoader(soa, h_class_loader, h_dex_elements, &info)) { return nullptr; } + std::unique_ptr<ClassLoaderContext> result(new ClassLoaderContext(/*owns_the_dex_files=*/ false)); + result->class_loader_chain_ = std::move(info); + return result; } static bool IsAbsoluteLocation(const std::string& location) { @@ -1130,8 +1145,8 @@ bool ClassLoaderContext::ClassLoaderInfoMatch( if (info.shared_libraries.size() != expected_info.shared_libraries.size()) { LOG(WARNING) << "ClassLoaderContext shared library size mismatch. " - << "Expected=" << expected_info.classpath.size() - << ", found=" << info.classpath.size() + << "Expected=" << expected_info.shared_libraries.size() + << ", found=" << info.shared_libraries.size() << " (" << context_spec << " | " << EncodeContextForOatFile("") << ")"; return false; } diff --git a/runtime/class_loader_context.h b/runtime/class_loader_context.h index 71f40ac167..83fb2de595 100644 --- a/runtime/class_loader_context.h +++ b/runtime/class_loader_context.h @@ -227,12 +227,13 @@ class ClassLoaderContext { // of the call. void CheckDexFilesOpened(const std::string& calling_method) const; - // Adds the `class_loader` info to the context. + // Creates the `ClassLoaderInfo` representing`class_loader`. // The dex file present in `dex_elements` array (if not null) will be added at the end of // the classpath. - bool AddInfoToContextFromClassLoader(ScopedObjectAccessAlreadyRunnable& soa, - Handle<mirror::ClassLoader> class_loader, - Handle<mirror::ObjectArray<mirror::Object>> dex_elements) + static bool CreateInfoFromClassLoader(ScopedObjectAccessAlreadyRunnable& soa, + Handle<mirror::ClassLoader> class_loader, + Handle<mirror::ObjectArray<mirror::Object>> dex_elements, + std::unique_ptr<ClassLoaderInfo>* return_info) 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 0756982b65..3c5f1ef95d 100644 --- a/runtime/class_loader_context_test.cc +++ b/runtime/class_loader_context_test.cc @@ -23,6 +23,7 @@ #include "base/dchecked_vector.h" #include "base/stl_util.h" #include "class_linker.h" +#include "class_root.h" #include "common_runtime_test.h" #include "dex/dex_file.h" #include "handle_scope-inl.h" @@ -30,6 +31,7 @@ #include "mirror/class.h" #include "mirror/class_loader.h" #include "mirror/object-inl.h" +#include "mirror/object_array-alloc-inl.h" #include "oat_file_assistant.h" #include "runtime.h" #include "scoped_thread_state_change-inl.h" @@ -1230,4 +1232,30 @@ TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchAfterEncodingMultide ClassLoaderContext::VerificationResult::kVerifies); } +TEST_F(ClassLoaderContextTest, CreateContextForClassLoaderWithSharedLibraries) { + jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr); + + ScopedObjectAccess soa(Thread::Current()); + StackHandleScope<1> hs(soa.Self()); + Handle<mirror::ObjectArray<mirror::ClassLoader>> libraries = hs.NewHandle( + mirror::ObjectArray<mirror::ClassLoader>::Alloc( + soa.Self(), + GetClassRoot<mirror::ObjectArray<mirror::ClassLoader>>(), + 1)); + libraries->Set(0, soa.Decode<mirror::ClassLoader>(class_loader_a)); + + jobject class_loader_b = LoadDexInPathClassLoader( + "ForClassLoaderB", nullptr, soa.AddLocalReference<jobject>(libraries.Get())); + + std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_b); + ASSERT_TRUE(context != nullptr); + std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("ForClassLoaderB"); + VerifyClassLoaderPCL(context.get(), 0, dex_files[0]->GetLocation()); + dex_files = OpenTestDexFiles("ForClassLoaderA"); + VerifyClassLoaderSharedLibraryPCL(context.get(), 0, 0, dex_files[0]->GetLocation()); + + ASSERT_EQ(context->VerifyClassLoaderContextMatch(context->EncodeContextForOatFile("")), + ClassLoaderContext::VerificationResult::kVerifies); +} + } // namespace art diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc index fcf6bb25e3..6d21f15c7a 100644 --- a/runtime/common_runtime_test.cc +++ b/runtime/common_runtime_test.cc @@ -273,7 +273,8 @@ jobject CommonRuntimeTestImpl::LoadDex(const char* dex_name) { jobject CommonRuntimeTestImpl::LoadDexInWellKnownClassLoader(const std::string& dex_name, jclass loader_class, - jobject parent_loader) { + jobject parent_loader, + jobject shared_libraries) { std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles(dex_name.c_str()); std::vector<const DexFile*> class_path; CHECK_NE(0U, dex_files.size()); @@ -288,7 +289,8 @@ jobject CommonRuntimeTestImpl::LoadDexInWellKnownClassLoader(const std::string& self, class_path, loader_class, - parent_loader); + parent_loader, + shared_libraries); { // Verify we build the correct chain. @@ -315,10 +317,12 @@ jobject CommonRuntimeTestImpl::LoadDexInWellKnownClassLoader(const std::string& } jobject CommonRuntimeTestImpl::LoadDexInPathClassLoader(const std::string& dex_name, - jobject parent_loader) { + jobject parent_loader, + jobject shared_libraries) { return LoadDexInWellKnownClassLoader(dex_name, WellKnownClasses::dalvik_system_PathClassLoader, - parent_loader); + parent_loader, + shared_libraries); } jobject CommonRuntimeTestImpl::LoadDexInDelegateLastClassLoader(const std::string& dex_name, diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h index c48ab3629c..0fee797015 100644 --- a/runtime/common_runtime_test.h +++ b/runtime/common_runtime_test.h @@ -115,11 +115,14 @@ class CommonRuntimeTestImpl : public CommonArtTestImpl { jobject LoadMultiDex(const char* first_dex_name, const char* second_dex_name) REQUIRES_SHARED(Locks::mutator_lock_); - jobject LoadDexInPathClassLoader(const std::string& dex_name, jobject parent_loader); + jobject LoadDexInPathClassLoader(const std::string& dex_name, + jobject parent_loader, + jobject shared_libraries = nullptr); jobject LoadDexInDelegateLastClassLoader(const std::string& dex_name, jobject parent_loader); jobject LoadDexInWellKnownClassLoader(const std::string& dex_name, jclass loader_class, - jobject parent_loader); + jobject parent_loader, + jobject shared_libraries = nullptr); std::unique_ptr<Runtime> runtime_; |