From fd1ae75a03b0b17fdbbb0097e856f494edf12312 Mon Sep 17 00:00:00 2001 From: Andreas Gampe Date: Fri, 28 Oct 2016 15:34:26 -0700 Subject: [PATCH] ART: Generalize FindClassInPathClassLoader Also accept DexClassLoader. Do a fast check for subclasses of BaseDexClassLoader that are in the boot classpath. Bug: 32510706 Test: m test-art-host Change-Id: I7d79aa90e0241e7717c5d146d1123f41746e4ffa --- runtime/class_linker.cc | 34 ++++++++++++++++++++----------- runtime/class_linker.h | 16 +++++++-------- runtime/native/java_lang_VMClassLoader.cc | 2 +- runtime/well_known_classes.cc | 2 ++ runtime/well_known_classes.h | 1 + 5 files changed, 34 insertions(+), 21 deletions(-) diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 73524af0b..d3d30d4ce 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -2329,12 +2329,12 @@ ClassPathEntry FindInClassPath(const char* descriptor, return ClassPathEntry(nullptr, nullptr); } -bool ClassLinker::FindClassInPathClassLoader(ScopedObjectAccessAlreadyRunnable& soa, - Thread* self, - const char* descriptor, - size_t hash, - Handle class_loader, - ObjPtr* result) { +bool ClassLinker::FindClassInBaseDexClassLoader(ScopedObjectAccessAlreadyRunnable& soa, + Thread* self, + const char* descriptor, + size_t hash, + Handle class_loader, + ObjPtr* result) { // Termination case: boot class-loader. if (IsBootClassLoader(soa, class_loader.Get())) { // The boot class loader, search the boot class path. @@ -2364,14 +2364,24 @@ bool ClassLinker::FindClassInPathClassLoader(ScopedObjectAccessAlreadyRunnable& // Unsupported class-loader? if (soa.Decode(WellKnownClasses::dalvik_system_PathClassLoader) != class_loader->GetClass()) { - *result = nullptr; - return false; + // PathClassLoader is the most common case, so it's the one we check first. For secondary dex + // files, we also check DexClassLoader here. + if (soa.Decode(WellKnownClasses::dalvik_system_DexClassLoader) != + class_loader->GetClass()) { + *result = nullptr; + return false; + } } // Handles as RegisterDexFile may allocate dex caches (and cause thread suspension). StackHandleScope<4> hs(self); Handle h_parent(hs.NewHandle(class_loader->GetParent())); - bool recursive_result = FindClassInPathClassLoader(soa, self, descriptor, hash, h_parent, result); + bool recursive_result = FindClassInBaseDexClassLoader(soa, + self, + descriptor, + hash, + h_parent, + result); if (!recursive_result) { // Something wrong up the chain. @@ -2493,14 +2503,14 @@ mirror::Class* ClassLinker::FindClass(Thread* self, } else { ScopedObjectAccessUnchecked soa(self); ObjPtr cp_klass; - if (FindClassInPathClassLoader(soa, self, descriptor, hash, class_loader, &cp_klass)) { + if (FindClassInBaseDexClassLoader(soa, self, descriptor, hash, class_loader, &cp_klass)) { // The chain was understood. So the value in cp_klass is either the class we were looking // for, or not found. if (cp_klass != nullptr) { return cp_klass.Ptr(); } - // TODO: We handle the boot classpath loader in FindClassInPathClassLoader. Try to unify this - // and the branch above. TODO: throw the right exception here. + // TODO: We handle the boot classpath loader in FindClassInBaseDexClassLoader. Try to unify + // this and the branch above. TODO: throw the right exception here. // We'll let the Java-side rediscover all this and throw the exception with the right stack // trace. diff --git a/runtime/class_linker.h b/runtime/class_linker.h index 3248d0e3d..442605607 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -794,17 +794,17 @@ class ClassLinker { void FixupStaticTrampolines(ObjPtr klass) REQUIRES_SHARED(Locks::mutator_lock_); - // Finds a class in the path class loader, loading it if necessary without using JNI. Hash + // Finds a class in a Path- or DexClassLoader, loading it if necessary without using JNI. Hash // function is supposed to be ComputeModifiedUtf8Hash(descriptor). Returns true if the // class-loader chain could be handled, false otherwise, i.e., a non-supported class-loader // was encountered while walking the parent chain (currently only BootClassLoader and // PathClassLoader are supported). - bool FindClassInPathClassLoader(ScopedObjectAccessAlreadyRunnable& soa, - Thread* self, - const char* descriptor, - size_t hash, - Handle class_loader, - ObjPtr* result) + bool FindClassInBaseDexClassLoader(ScopedObjectAccessAlreadyRunnable& soa, + Thread* self, + const char* descriptor, + size_t hash, + Handle class_loader, + ObjPtr* result) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!dex_lock_); @@ -1200,7 +1200,7 @@ class ClassLinker { friend struct CompilationHelper; // For Compile in ImageTest. friend class ImageDumper; // for DexLock friend class ImageWriter; // for GetClassRoots - friend class VMClassLoader; // for LookupClass and FindClassInPathClassLoader. + friend class VMClassLoader; // for LookupClass and FindClassInBaseDexClassLoader. friend class JniCompilerTest; // for GetRuntimeQuickGenericJniStub friend class JniInternalTest; // for GetRuntimeQuickGenericJniStub ART_FRIEND_TEST(ClassLinkerTest, RegisterDexFileName); // for DexLock, and RegisterDexFileLocked diff --git a/runtime/native/java_lang_VMClassLoader.cc b/runtime/native/java_lang_VMClassLoader.cc index e5bab3687..284d2d10c 100644 --- a/runtime/native/java_lang_VMClassLoader.cc +++ b/runtime/native/java_lang_VMClassLoader.cc @@ -48,7 +48,7 @@ class VMClassLoader { Handle class_loader) REQUIRES_SHARED(Locks::mutator_lock_) { ObjPtr result; - if (cl->FindClassInPathClassLoader(soa, self, descriptor, hash, class_loader, &result)) { + if (cl->FindClassInBaseDexClassLoader(soa, self, descriptor, hash, class_loader, &result)) { return result; } return nullptr; diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc index 0f4ae521e..2797d8570 100644 --- a/runtime/well_known_classes.cc +++ b/runtime/well_known_classes.cc @@ -35,6 +35,7 @@ jclass WellKnownClasses::com_android_dex_Dex; jclass WellKnownClasses::dalvik_annotation_optimization_CriticalNative; jclass WellKnownClasses::dalvik_annotation_optimization_FastNative; jclass WellKnownClasses::dalvik_system_BaseDexClassLoader; +jclass WellKnownClasses::dalvik_system_DexClassLoader; jclass WellKnownClasses::dalvik_system_DexFile; jclass WellKnownClasses::dalvik_system_DexPathList; jclass WellKnownClasses::dalvik_system_DexPathList__Element; @@ -266,6 +267,7 @@ void WellKnownClasses::Init(JNIEnv* env) { CacheClass(env, "dalvik/annotation/optimization/CriticalNative"); dalvik_annotation_optimization_FastNative = CacheClass(env, "dalvik/annotation/optimization/FastNative"); dalvik_system_BaseDexClassLoader = CacheClass(env, "dalvik/system/BaseDexClassLoader"); + dalvik_system_DexClassLoader = CacheClass(env, "dalvik/system/DexClassLoader"); dalvik_system_DexFile = CacheClass(env, "dalvik/system/DexFile"); dalvik_system_DexPathList = CacheClass(env, "dalvik/system/DexPathList"); dalvik_system_DexPathList__Element = CacheClass(env, "dalvik/system/DexPathList$Element"); diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h index d07977a49..227996ad9 100644 --- a/runtime/well_known_classes.h +++ b/runtime/well_known_classes.h @@ -48,6 +48,7 @@ struct WellKnownClasses { static jclass dalvik_annotation_optimization_CriticalNative; static jclass dalvik_annotation_optimization_FastNative; static jclass dalvik_system_BaseDexClassLoader; + static jclass dalvik_system_DexClassLoader; static jclass dalvik_system_DexFile; static jclass dalvik_system_DexPathList; static jclass dalvik_system_DexPathList__Element; -- 2.11.0