diff options
author | 2017-07-26 16:18:11 +0000 | |
---|---|---|
committer | 2017-07-26 16:18:11 +0000 | |
commit | b22ae40038aeeebb16936fbf62b48f080d6e7ef4 (patch) | |
tree | cef0433bc2a897ed8afccc8d763922505543c1db | |
parent | 2c2e13ec24bff70db6e49270b9d4d787add9925e (diff) | |
parent | 1a509c8effc938ba3da0f90ad83abb124b296386 (diff) |
Merge "Be prepared to handle empty class loader contexts"
-rw-r--r-- | runtime/class_loader_context.cc | 14 | ||||
-rw-r--r-- | runtime/class_loader_context_test.cc | 41 |
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"); |