summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Calin Juravle <calin@google.com> 2017-07-26 16:18:11 +0000
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2017-07-26 16:18:11 +0000
commitb22ae40038aeeebb16936fbf62b48f080d6e7ef4 (patch)
treecef0433bc2a897ed8afccc8d763922505543c1db
parent2c2e13ec24bff70db6e49270b9d4d787add9925e (diff)
parent1a509c8effc938ba3da0f90ad83abb124b296386 (diff)
Merge "Be prepared to handle empty class loader contexts"
-rw-r--r--runtime/class_loader_context.cc14
-rw-r--r--runtime/class_loader_context_test.cc41
2 files changed, 52 insertions, 3 deletions
diff --git a/runtime/class_loader_context.cc b/runtime/class_loader_context.cc
index eab3b86d3d..ff440d7bba 100644
--- a/runtime/class_loader_context.cc
+++ b/runtime/class_loader_context.cc
@@ -145,6 +145,10 @@ ClassLoaderContext::ExtractClassLoaderType(const std::string& class_loader_spec)
// ClasspathElem is the path of dex/jar/apk file.
bool ClassLoaderContext::Parse(const std::string& spec, bool parse_checksums) {
if (spec.empty()) {
+ // By default we load the dex files in a PathClassLoader.
+ // So an empty spec is equivalent to an empty PathClassLoader (this happens when running
+ // tests)
+ class_loader_chain_.push_back(ClassLoaderInfo(kPathClassLoader));
return true;
}
@@ -265,12 +269,16 @@ std::string ClassLoaderContext::EncodeContextForOatFile(const std::string& base_
return OatFile::kSpecialSharedLibrary;
}
+ std::ostringstream out;
if (class_loader_chain_.empty()) {
- return "";
+ // We can get in this situation if the context was created with a class path containing the
+ // source dex files which were later removed (happens during run-tests).
+ out << GetClassLoaderTypeName(kPathClassLoader)
+ << kClassLoaderOpeningMark
+ << kClassLoaderClosingMark;
+ return out.str();
}
- std::ostringstream out;
-
for (size_t i = 0; i < class_loader_chain_.size(); i++) {
const ClassLoaderInfo& info = class_loader_chain_[i];
if (i > 0) {
diff --git a/runtime/class_loader_context_test.cc b/runtime/class_loader_context_test.cc
index 5655aecbe5..2b85188e38 100644
--- a/runtime/class_loader_context_test.cc
+++ b/runtime/class_loader_context_test.cc
@@ -161,6 +161,19 @@ class ClassLoaderContextTest : public CommonRuntimeTest {
}
};
+TEST_F(ClassLoaderContextTest, ParseValidEmptyContext) {
+ std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("");
+ // An empty context should create a single empty PathClassLoader.
+ VerifyContextSize(context.get(), 1);
+ VerifyClassLoaderPCL(context.get(), 0, "");
+}
+
+TEST_F(ClassLoaderContextTest, ParseValidSharedLibraryContext) {
+ std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("&");
+ // An shared library context should have no class loader in the chain.
+ VerifyContextSize(context.get(), 0);
+}
+
TEST_F(ClassLoaderContextTest, ParseValidContextPCL) {
std::unique_ptr<ClassLoaderContext> context =
ClassLoaderContext::Create("PCL[a.dex]");
@@ -312,6 +325,34 @@ TEST_F(ClassLoaderContextTest, CreateClassLoaderWithEmptyContext) {
soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
}
+TEST_F(ClassLoaderContextTest, CreateClassLoaderWithSharedLibraryContext) {
+ std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("&");
+
+ ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
+
+ std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
+
+ std::vector<const DexFile*> compilation_sources_raw =
+ MakeNonOwningPointerVector(compilation_sources);
+ jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
+ ASSERT_TRUE(jclass_loader != nullptr);
+
+ ScopedObjectAccess soa(Thread::Current());
+
+ StackHandleScope<1> hs(soa.Self());
+ Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
+ soa.Decode<mirror::ClassLoader>(jclass_loader));
+
+ // A shared library context should create a single PathClassLoader with only the compilation
+ // sources.
+ VerifyClassLoaderDexFiles(soa,
+ class_loader,
+ WellKnownClasses::dalvik_system_PathClassLoader,
+ compilation_sources_raw);
+ ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
+ soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
+}
+
TEST_F(ClassLoaderContextTest, CreateClassLoaderWithComplexChain) {
// Setup the context.
std::vector<std::unique_ptr<const DexFile>> classpath_dex_a = OpenTestDexFiles("ForClassLoaderA");