Support shared libraries in ClassLoaderContext::CreateClassLoader.
bug: 111174995
Test: dex2oat_test, class_loader_context_test
Change-Id: I482012eca408f9e064d7c3d787662376e1b0de3b
diff --git a/runtime/class_loader_context.cc b/runtime/class_loader_context.cc
index 0bae60a..518be00 100644
--- a/runtime/class_loader_context.cc
+++ b/runtime/class_loader_context.cc
@@ -24,11 +24,14 @@
#include "base/stl_util.h"
#include "class_linker.h"
#include "class_loader_utils.h"
+#include "class_root.h"
#include "dex/art_dex_file_loader.h"
#include "dex/dex_file.h"
#include "dex/dex_file_loader.h"
#include "handle_scope-inl.h"
#include "jni/jni_internal.h"
+#include "mirror/object_array-alloc-inl.h"
+#include "nativehelper/scoped_local_ref.h"
#include "oat_file_assistant.h"
#include "obj_ptr-inl.h"
#include "runtime.h"
@@ -571,20 +574,57 @@
UNREACHABLE();
}
-static jobject CreateClassLoaderInternal(Thread* self,
- const ClassLoaderContext::ClassLoaderInfo& info)
+static ObjPtr<mirror::ClassLoader> CreateClassLoaderInternal(
+ Thread* self,
+ ScopedObjectAccess& soa,
+ const ClassLoaderContext::ClassLoaderInfo& info,
+ bool add_compilation_sources,
+ const std::vector<const DexFile*>& compilation_sources)
REQUIRES_SHARED(Locks::mutator_lock_) {
- CHECK(info.shared_libraries.empty()) << "Class loader shared library not implemented yet";
- jobject parent = nullptr;
+ StackHandleScope<3> hs(self);
+ MutableHandle<mirror::ObjectArray<mirror::ClassLoader>> libraries(
+ hs.NewHandle<mirror::ObjectArray<mirror::ClassLoader>>(nullptr));
+
+ if (!info.shared_libraries.empty()) {
+ libraries.Assign(mirror::ObjectArray<mirror::ClassLoader>::Alloc(
+ self,
+ GetClassRoot<mirror::ObjectArray<mirror::ClassLoader>>(),
+ info.shared_libraries.size()));
+ for (uint32_t i = 0; i < info.shared_libraries.size(); ++i) {
+ // We should only add the compilation sources to the first class loader.
+ libraries->Set(i,
+ CreateClassLoaderInternal(
+ self,
+ soa,
+ *info.shared_libraries[i].get(),
+ /* add_compilation_sources= */ false,
+ compilation_sources));
+ }
+ }
+
+ MutableHandle<mirror::ClassLoader> parent = hs.NewHandle<mirror::ClassLoader>(nullptr);
if (info.parent != nullptr) {
- parent = CreateClassLoaderInternal(self, *info.parent.get());
+ // We should only add the compilation sources to the first class loader.
+ parent.Assign(CreateClassLoaderInternal(
+ self, soa, *info.parent.get(), /* add_compilation_sources= */ false, compilation_sources));
}
std::vector<const DexFile*> class_path_files = MakeNonOwningPointerVector(
info.opened_dex_files);
+ if (add_compilation_sources) {
+ // For the first class loader, its classpath comes first, followed by compilation sources.
+ // This ensures that whenever we need to resolve classes from it the classpath elements
+ // come first.
+ class_path_files.insert(class_path_files.end(),
+ compilation_sources.begin(),
+ compilation_sources.end());
+ }
+ Handle<mirror::Class> loader_class = hs.NewHandle<mirror::Class>(
+ soa.Decode<mirror::Class>(GetClassLoaderClass(info.type)));
return Runtime::Current()->GetClassLinker()->CreateWellKnownClassLoader(
self,
class_path_files,
- GetClassLoaderClass(info.type),
+ loader_class,
+ libraries,
parent);
}
@@ -598,30 +638,21 @@
ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
if (class_loader_chain_ == nullptr) {
+ CHECK(special_shared_library_);
return class_linker->CreatePathClassLoader(self, compilation_sources);
}
// Create the class loader of the parent.
- jobject parent = nullptr;
- if (class_loader_chain_->parent != nullptr) {
- parent = CreateClassLoaderInternal(self, *class_loader_chain_->parent.get());
- }
-
- // We set up all the parents. Move on to create the first class loader.
- // Its classpath comes first, followed by compilation sources. This ensures that whenever
- // we need to resolve classes from it the classpath elements come first.
-
- std::vector<const DexFile*> first_class_loader_classpath = MakeNonOwningPointerVector(
- class_loader_chain_->opened_dex_files);
- first_class_loader_classpath.insert(first_class_loader_classpath.end(),
- compilation_sources.begin(),
- compilation_sources.end());
-
- return class_linker->CreateWellKnownClassLoader(
- self,
- first_class_loader_classpath,
- GetClassLoaderClass(class_loader_chain_->type),
- parent);
+ ObjPtr<mirror::ClassLoader> loader =
+ CreateClassLoaderInternal(self,
+ soa,
+ *class_loader_chain_.get(),
+ /* add_compilation_sources= */ true,
+ compilation_sources);
+ // Make it a global ref and return.
+ ScopedLocalRef<jobject> local_ref(
+ soa.Env(), soa.Env()->AddLocalReference<jobject>(loader));
+ return soa.Env()->NewGlobalRef(local_ref.get());
}
std::vector<const DexFile*> ClassLoaderContext::FlattenOpenedDexFiles() const {