diff options
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r-- | runtime/class_linker.cc | 214 |
1 files changed, 140 insertions, 74 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 67513f9ce6..639fa7ec92 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -798,6 +798,8 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b FindSystemClass(self, "Ljava/lang/StackTraceElement;")); SetClassRoot(ClassRoot::kJavaLangStackTraceElementArrayClass, FindSystemClass(self, "[Ljava/lang/StackTraceElement;")); + SetClassRoot(ClassRoot::kJavaLangClassLoaderArrayClass, + FindSystemClass(self, "[Ljava/lang/ClassLoader;")); // Create conflict tables that depend on the class linker. runtime->FixupConflictTables(); @@ -1543,26 +1545,6 @@ void AppImageLoadingHelper::HandleAppImageStrings(gc::space::ImageSpace* space) } } -// Update the class loader. Should only be used on classes in the image space. -class UpdateClassLoaderVisitor { - public: - UpdateClassLoaderVisitor(gc::space::ImageSpace* space, ObjPtr<mirror::ClassLoader> class_loader) - : space_(space), - class_loader_(class_loader) {} - - bool operator()(ObjPtr<mirror::Class> klass) const REQUIRES_SHARED(Locks::mutator_lock_) { - // Do not update class loader for boot image classes where the app image - // class loader is only the initiating loader but not the defining loader. - if (klass->GetClassLoader() != nullptr) { - klass->SetClassLoader(class_loader_); - } - return true; - } - - gc::space::ImageSpace* const space_; - ObjPtr<mirror::ClassLoader> const class_loader_; -}; - static std::unique_ptr<const DexFile> OpenOatDexFile(const OatFile* oat_file, const char* location, std::string* error_msg) @@ -2036,9 +2018,17 @@ bool ClassLinker::AddImageSpace( ScopedTrace trace("AppImage:UpdateClassLoaders"); // Update class loader and resolved strings. If added_class_table is false, the resolved // strings were forwarded UpdateAppImageClassLoadersAndDexCaches. - UpdateClassLoaderVisitor visitor(space, class_loader.Get()); + ObjPtr<mirror::ClassLoader> loader(class_loader.Get()); for (const ClassTable::TableSlot& root : temp_set) { - visitor(root.Read()); + // Note: We probably don't need the read barrier unless we copy the app image objects into + // the region space. + ObjPtr<mirror::Class> klass(root.Read()); + // Do not update class loader for boot image classes where the app image + // class loader is only the initiating loader but not the defining loader. + // Avoid read barrier since we are comparing against null. + if (klass->GetClassLoader<kDefaultVerifyFlags, kWithoutReadBarrier>() != nullptr) { + klass->SetClassLoader</*kCheckTransaction=*/ false>(loader); + } } } @@ -2527,6 +2517,35 @@ ClassPathEntry FindInClassPath(const char* descriptor, return ClassPathEntry(nullptr, nullptr); } +bool ClassLinker::FindClassInSharedLibraries(ScopedObjectAccessAlreadyRunnable& soa, + Thread* self, + const char* descriptor, + size_t hash, + Handle<mirror::ClassLoader> class_loader, + /*out*/ ObjPtr<mirror::Class>* result) { + 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) { + return true; + } + + StackHandleScope<2> hs(self); + 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)); + if (!FindClassInBaseDexClassLoader(soa, self, descriptor, hash, temp_loader, result)) { + return false; // One of the shared libraries is not supported. + } + if (*result != nullptr) { + return true; // Found the class up the chain. + } + } + return true; +} + bool ClassLinker::FindClassInBaseDexClassLoader(ScopedObjectAccessAlreadyRunnable& soa, Thread* self, const char* descriptor, @@ -2542,6 +2561,7 @@ bool ClassLinker::FindClassInBaseDexClassLoader(ScopedObjectAccessAlreadyRunnabl if (IsPathOrDexClassLoader(soa, class_loader)) { // For regular path or dex class loader the search order is: // - parent + // - shared libraries // - class loader dex files // Handles as RegisterDexFile may allocate dex caches (and cause thread suspension). @@ -2554,6 +2574,13 @@ bool ClassLinker::FindClassInBaseDexClassLoader(ScopedObjectAccessAlreadyRunnabl return true; // Found the class up the chain. } + if (!FindClassInSharedLibraries(soa, self, descriptor, hash, class_loader, result)) { + return false; // One of the shared library loader is not supported. + } + if (*result != nullptr) { + return true; // Found the class in a shared library. + } + // Search the current class loader classpath. *result = FindClassInBaseDexClassLoaderClassPath(soa, descriptor, hash, class_loader); return true; @@ -2562,6 +2589,7 @@ bool ClassLinker::FindClassInBaseDexClassLoader(ScopedObjectAccessAlreadyRunnabl if (IsDelegateLastClassLoader(soa, class_loader)) { // For delegate last, the search order is: // - boot class path + // - shared libraries // - class loader dex files // - parent *result = FindClassInBootClassLoaderClassPath(self, descriptor, hash); @@ -2569,6 +2597,13 @@ bool ClassLinker::FindClassInBaseDexClassLoader(ScopedObjectAccessAlreadyRunnabl return true; // The class is part of the boot class path. } + if (!FindClassInSharedLibraries(soa, self, descriptor, hash, class_loader, result)) { + return false; // One of the shared library loader is not supported. + } + if (*result != nullptr) { + return true; // Found the class in a shared library. + } + *result = FindClassInBaseDexClassLoaderClassPath(soa, descriptor, hash, class_loader); if (*result != nullptr) { return true; // Found the class in the current class loader @@ -3112,7 +3147,7 @@ bool ClassLinker::ShouldUseInterpreterEntrypoint(ArtMethod* method, const void* return (jit == nullptr) || !jit->GetCodeCache()->ContainsPc(quick_code); } - if (runtime->IsNativeDebuggable()) { + if (runtime->IsNativeDebuggableZygoteOK()) { DCHECK(runtime->UseJitCompilation() && runtime->GetJit()->JitAtFirstUse()); // If we are doing native debugging, ignore application's AOT code, // since we want to JIT it (at first use) with extra stackmaps for native @@ -3435,14 +3470,8 @@ void ClassLinker::LoadField(const ClassAccessor::Field& field, dst->SetDexFieldIndex(field_idx); dst->SetDeclaringClass(klass.Get()); - // Get access flags from the DexFile. If this is a boot class path class, - // also set its runtime hidden API access flags. - uint32_t access_flags = field.GetAccessFlags(); - if (klass->IsBootStrapClassLoaded()) { - access_flags = hiddenapi::EncodeForRuntime( - access_flags, static_cast<hiddenapi::ApiList>(field.GetHiddenapiFlags())); - } - dst->SetAccessFlags(access_flags); + // Get access flags from the DexFile and set hiddenapi runtime access flags. + dst->SetAccessFlags(field.GetAccessFlags() | hiddenapi::CreateRuntimeFlags(field)); } void ClassLinker::LoadMethod(const DexFile& dex_file, @@ -3458,13 +3487,8 @@ void ClassLinker::LoadMethod(const DexFile& dex_file, dst->SetDeclaringClass(klass.Get()); dst->SetCodeItemOffset(method.GetCodeItemOffset()); - // Get access flags from the DexFile. If this is a boot class path class, - // also set its runtime hidden API access flags. - uint32_t access_flags = method.GetAccessFlags(); - if (klass->IsBootStrapClassLoaded()) { - access_flags = hiddenapi::EncodeForRuntime( - access_flags, static_cast<hiddenapi::ApiList>(method.GetHiddenapiFlags())); - } + // Get access flags from the DexFile and set hiddenapi runtime access flags. + uint32_t access_flags = method.GetAccessFlags() | hiddenapi::CreateRuntimeFlags(method); if (UNLIKELY(strcmp("finalize", method_name) == 0)) { // Set finalizable flag on declaring class. @@ -5070,8 +5094,10 @@ bool ClassLinker::InitializeClass(Thread* self, Handle<mirror::Class> klass, ArtField* resolved_field = dex_cache->GetResolvedField(field_idx, image_pointer_size_); if (resolved_field == nullptr) { // Populating cache of a dex file which defines `klass` should always be allowed. - DCHECK_EQ(hiddenapi::GetMemberAction( - field, class_loader.Get(), dex_cache.Get(), hiddenapi::kNone), hiddenapi::kAllow); + DCHECK(!hiddenapi::ShouldDenyAccessToMember( + field, + hiddenapi::AccessContext(class_loader.Get(), dex_cache.Get()), + hiddenapi::AccessMethod::kNone)); dex_cache->SetResolvedField(field_idx, field, image_pointer_size_); } else { DCHECK_EQ(field, resolved_field); @@ -8102,8 +8128,9 @@ ArtMethod* ClassLinker::FindResolvedMethod(ObjPtr<mirror::Class> klass, } DCHECK(resolved == nullptr || resolved->GetDeclaringClassUnchecked() != nullptr); if (resolved != nullptr && - hiddenapi::GetMemberAction( - resolved, class_loader, dex_cache, hiddenapi::kLinking) == hiddenapi::kDeny) { + hiddenapi::ShouldDenyAccessToMember(resolved, + hiddenapi::AccessContext(class_loader, dex_cache), + hiddenapi::AccessMethod::kLinking)) { resolved = nullptr; } if (resolved != nullptr) { @@ -8133,11 +8160,9 @@ static bool CheckNoSuchMethod(ArtMethod* method, ObjPtr<mirror::ClassLoader> class_loader) REQUIRES_SHARED(Locks::mutator_lock_) { return method == nullptr || - hiddenapi::GetMemberAction(method, - class_loader, - dex_cache, - hiddenapi::kNone) // do not print warnings - == hiddenapi::kDeny; + hiddenapi::ShouldDenyAccessToMember(method, + hiddenapi::AccessContext(class_loader, dex_cache), + hiddenapi::AccessMethod::kNone); // no warnings } ArtMethod* ClassLinker::FindIncompatibleMethod(ObjPtr<mirror::Class> klass, @@ -8273,8 +8298,10 @@ ArtMethod* ClassLinker::ResolveMethodWithoutInvokeType(uint32_t method_idx, resolved = klass->FindClassMethod(dex_cache.Get(), method_idx, image_pointer_size_); } if (resolved != nullptr && - hiddenapi::GetMemberAction( - resolved, class_loader.Get(), dex_cache.Get(), hiddenapi::kLinking) == hiddenapi::kDeny) { + hiddenapi::ShouldDenyAccessToMember( + resolved, + hiddenapi::AccessContext(class_loader.Get(), dex_cache.Get()), + hiddenapi::AccessMethod::kLinking)) { resolved = nullptr; } return resolved; @@ -8373,8 +8400,9 @@ ArtField* ClassLinker::FindResolvedField(ObjPtr<mirror::Class> klass, } if (resolved != nullptr && - hiddenapi::GetMemberAction( - resolved, class_loader, dex_cache, hiddenapi::kLinking) == hiddenapi::kDeny) { + hiddenapi::ShouldDenyAccessToMember(resolved, + hiddenapi::AccessContext(class_loader, dex_cache), + hiddenapi::AccessMethod::kLinking)) { resolved = nullptr; } @@ -8399,8 +8427,9 @@ ArtField* ClassLinker::FindResolvedFieldJLS(ObjPtr<mirror::Class> klass, resolved = mirror::Class::FindField(self, klass, name, type); if (resolved != nullptr && - hiddenapi::GetMemberAction( - resolved, class_loader, dex_cache, hiddenapi::kLinking) == hiddenapi::kDeny) { + hiddenapi::ShouldDenyAccessToMember(resolved, + hiddenapi::AccessContext(class_loader, dex_cache), + hiddenapi::AccessMethod::kLinking)) { resolved = nullptr; } @@ -8967,21 +8996,14 @@ void ClassLinker::AllocAndSetPrimitiveArrayClassRoot(Thread* self, CheckSystemClass(self, primitive_array_class, descriptor); } -jobject ClassLinker::CreateWellKnownClassLoader(Thread* self, - const std::vector<const DexFile*>& dex_files, - jclass loader_class, - jobject parent_loader) { - CHECK(self->GetJniEnv()->IsSameObject(loader_class, - WellKnownClasses::dalvik_system_PathClassLoader) || - self->GetJniEnv()->IsSameObject(loader_class, - WellKnownClasses::dalvik_system_DelegateLastClassLoader)); - - // SOAAlreadyRunnable is protected, and we need something to add a global reference. - // We could move the jobject to the callers, but all call-sites do this... - ScopedObjectAccessUnchecked soa(self); +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) { - // For now, create a libcore-level DexFile for each ART DexFile. This "explodes" multidex. - StackHandleScope<6> hs(self); + StackHandleScope<5> hs(self); ArtField* dex_elements_field = jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList_dexElements); @@ -9071,8 +9093,8 @@ jobject ClassLinker::CreateWellKnownClassLoader(Thread* self, } // Create the class loader.. - Handle<mirror::Class> h_loader_class = hs.NewHandle(soa.Decode<mirror::Class>(loader_class)); - Handle<mirror::Object> h_class_loader = hs.NewHandle(h_loader_class->AllocObject(self)); + Handle<mirror::ClassLoader> h_class_loader = hs.NewHandle<mirror::ClassLoader>( + ObjPtr<mirror::ClassLoader>::DownCast(loader_class->AllocObject(self))); DCHECK(h_class_loader != nullptr); // Set DexPathList. ArtField* path_list_field = @@ -9088,15 +9110,59 @@ jobject ClassLinker::CreateWellKnownClassLoader(Thread* self, "parent", "Ljava/lang/ClassLoader;"); DCHECK(parent_field != nullptr); + if (parent_loader.Get() == nullptr) { + ScopedObjectAccessUnchecked soa(self); + ObjPtr<mirror::Object> boot_loader(soa.Decode<mirror::Class>( + WellKnownClasses::java_lang_BootClassLoader)->AllocObject(self)); + parent_field->SetObject<false>(h_class_loader.Get(), boot_loader); + } else { + parent_field->SetObject<false>(h_class_loader.Get(), parent_loader.Get()); + } + + ArtField* shared_libraries_field = + jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_sharedLibraryLoaders); + DCHECK(shared_libraries_field != nullptr); + shared_libraries_field->SetObject<false>(h_class_loader.Get(), shared_libraries.Get()); + + return h_class_loader.Get(); +} - ObjPtr<mirror::Object> parent = (parent_loader != nullptr) - ? soa.Decode<mirror::ClassLoader>(parent_loader) - : soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader)->AllocObject(self); - parent_field->SetObject<false>(h_class_loader.Get(), parent); +jobject ClassLinker::CreateWellKnownClassLoader(Thread* self, + const std::vector<const DexFile*>& dex_files, + jclass loader_class, + jobject parent_loader) { + CHECK(self->GetJniEnv()->IsSameObject(loader_class, + WellKnownClasses::dalvik_system_PathClassLoader) || + self->GetJniEnv()->IsSameObject(loader_class, + WellKnownClasses::dalvik_system_DelegateLastClassLoader)); + + // SOAAlreadyRunnable is protected, and we need something to add a global reference. + // We could move the jobject to the callers, but all call-sites do this... + ScopedObjectAccessUnchecked soa(self); + + // For now, create a libcore-level DexFile for each ART DexFile. This "explodes" multidex. + StackHandleScope<3> 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); + + ObjPtr<mirror::ClassLoader> loader = CreateWellKnownClassLoader( + self, + dex_files, + h_loader_class, + shared_libraries, + parent); // Make it a global ref and return. ScopedLocalRef<jobject> local_ref( - soa.Env(), soa.Env()->AddLocalReference<jobject>(h_class_loader.Get())); + soa.Env(), soa.Env()->AddLocalReference<jobject>(loader)); return soa.Env()->NewGlobalRef(local_ref.get()); } |