diff options
| -rw-r--r-- | dex2oat/linker/image_writer.cc | 34 | ||||
| -rw-r--r-- | runtime/class_linker.cc | 109 | ||||
| -rw-r--r-- | runtime/class_linker.h | 21 |
3 files changed, 96 insertions, 68 deletions
diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc index 9e5cd8035c..492f9ce5c1 100644 --- a/dex2oat/linker/image_writer.cc +++ b/dex2oat/linker/image_writer.cc @@ -1067,18 +1067,12 @@ void ImageWriter::PruneAndPreloadDexCache(ObjPtr<mirror::DexCache> dex_cache, } if (method == nullptr || i < stored_index) { if (last_class != nullptr) { - const char* name = dex_file.StringDataByIdx(method_id.name_idx_); - Signature signature = dex_file.GetMethodSignature(method_id); - if (last_class->IsInterface()) { - method = last_class->FindInterfaceMethod(name, signature, target_ptr_size_); - } else { - method = last_class->FindClassMethod(name, signature, target_ptr_size_); - } - if (method != nullptr) { - // If the referenced class is in the image, the defining class must also be there. - DCHECK(KeepClass(method->GetDeclaringClass())); - dex_cache->SetResolvedMethod(i, method, target_ptr_size_); - } + // Try to resolve the method with the class linker, which will insert + // it into the dex cache if successful. + method = class_linker->FindResolvedMethod(last_class, dex_cache, class_loader, i); + // If the referenced class is in the image, the defining class must also be there. + DCHECK(method == nullptr || KeepClass(method->GetDeclaringClass())); + DCHECK(method == nullptr || dex_cache->GetResolvedMethod(i, target_ptr_size_) == method); } } else { DCHECK_EQ(i, stored_index); @@ -1112,14 +1106,10 @@ void ImageWriter::PruneAndPreloadDexCache(ObjPtr<mirror::DexCache> dex_cache, } if (field == nullptr || i < stored_index) { if (last_class != nullptr) { - const char* name = dex_file.StringDataByIdx(field_id.name_idx_); - const char* type = dex_file.StringByTypeIdx(field_id.type_idx_); - field = mirror::Class::FindField(Thread::Current(), last_class, name, type); - if (field != nullptr) { - // If the referenced class is in the image, the defining class must also be there. - DCHECK(KeepClass(field->GetDeclaringClass())); - dex_cache->SetResolvedField(i, field, target_ptr_size_); - } + field = class_linker->FindResolvedFieldJLS(last_class, dex_cache, class_loader, i); + // If the referenced class is in the image, the defining class must also be there. + DCHECK(field == nullptr || KeepClass(field->GetDeclaringClass())); + DCHECK(field == nullptr || dex_cache->GetResolvedField(i, target_ptr_size_) == field); } } else { DCHECK_EQ(i, stored_index); @@ -1208,7 +1198,9 @@ void ImageWriter::PruneNonImageClasses() { } } for (ObjPtr<mirror::DexCache> dex_cache : dex_caches) { - PruneAndPreloadDexCache(dex_cache, class_loader); + // Pass the class loader associated with the DexCache. This can either be + // the app's `class_loader` or `nullptr` if boot class loader. + PruneAndPreloadDexCache(dex_cache, IsInBootImage(dex_cache.Ptr()) ? nullptr : class_loader); } // Drop the array class cache in the ClassLinker, as these are roots holding those classes live. diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 4141a37366..9c8b4383dc 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -4850,6 +4850,9 @@ bool ClassLinker::InitializeClass(Thread* self, Handle<mirror::Class> klass, const uint32_t field_idx = field->GetDexFieldIndex(); 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); dex_cache->SetResolvedField(field_idx, field, image_pointer_size_); } else { DCHECK_EQ(field, resolved_field); @@ -8053,26 +8056,8 @@ ArtField* ClassLinker::LookupResolvedField(uint32_t field_idx, return nullptr; } DCHECK(klass->IsResolved()); - Thread* self = is_static ? Thread::Current() : nullptr; - - // First try to find a field declared directly by `klass` by the field index. - ArtField* resolved_field = is_static - ? mirror::Class::FindStaticField(self, klass, dex_cache, field_idx) - : klass->FindInstanceField(dex_cache, field_idx); - - if (resolved_field == nullptr) { - // If not found in `klass` by field index, search the class hierarchy using the name and type. - const char* name = dex_file.GetFieldName(field_id); - const char* type = dex_file.GetFieldTypeDescriptor(field_id); - resolved_field = is_static - ? mirror::Class::FindStaticField(self, klass, name, type) - : klass->FindInstanceField(name, type); - } - if (resolved_field != nullptr) { - dex_cache->SetResolvedField(field_idx, resolved_field, image_pointer_size_); - } - return resolved_field; + return FindResolvedField(klass, dex_cache, class_loader, field_idx, is_static); } ArtField* ClassLinker::ResolveField(uint32_t field_idx, @@ -8087,39 +8072,18 @@ ArtField* ClassLinker::ResolveField(uint32_t field_idx, } const DexFile& dex_file = *dex_cache->GetDexFile(); const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx); - Thread* const self = Thread::Current(); ObjPtr<mirror::Class> klass = ResolveType(field_id.class_idx_, dex_cache, class_loader); if (klass == nullptr) { DCHECK(Thread::Current()->IsExceptionPending()); return nullptr; } - if (is_static) { - resolved = mirror::Class::FindStaticField(self, klass, dex_cache.Get(), field_idx); - } else { - resolved = klass->FindInstanceField(dex_cache.Get(), field_idx); - } - + resolved = FindResolvedField(klass, dex_cache.Get(), class_loader.Get(), field_idx, is_static); if (resolved == nullptr) { const char* name = dex_file.GetFieldName(field_id); const char* type = dex_file.GetFieldTypeDescriptor(field_id); - if (is_static) { - resolved = mirror::Class::FindStaticField(self, klass, name, type); - } else { - resolved = klass->FindInstanceField(name, type); - } - } - - if (resolved == nullptr || - hiddenapi::GetMemberAction( - resolved, class_loader.Get(), dex_cache.Get(), hiddenapi::kLinking) == hiddenapi::kDeny) { - const char* name = dex_file.GetFieldName(field_id); - const char* type = dex_file.GetFieldTypeDescriptor(field_id); ThrowNoSuchFieldError(is_static ? "static " : "instance ", klass, type, name); - return nullptr; } - - dex_cache->SetResolvedField(field_idx, resolved, image_pointer_size_); return resolved; } @@ -8134,26 +8098,77 @@ ArtField* ClassLinker::ResolveFieldJLS(uint32_t field_idx, } const DexFile& dex_file = *dex_cache->GetDexFile(); const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx); - Thread* self = Thread::Current(); ObjPtr<mirror::Class> klass = ResolveType(field_id.class_idx_, dex_cache, class_loader); if (klass == nullptr) { DCHECK(Thread::Current()->IsExceptionPending()); return nullptr; } - StringPiece name(dex_file.GetFieldName(field_id)); - StringPiece type(dex_file.GetFieldTypeDescriptor(field_id)); + resolved = FindResolvedFieldJLS(klass, dex_cache.Get(), class_loader.Get(), field_idx); + if (resolved == nullptr) { + const char* name = dex_file.GetFieldName(field_id); + const char* type = dex_file.GetFieldTypeDescriptor(field_id); + ThrowNoSuchFieldError("", klass, type, name); + } + return resolved; +} + +ArtField* ClassLinker::FindResolvedField(ObjPtr<mirror::Class> klass, + ObjPtr<mirror::DexCache> dex_cache, + ObjPtr<mirror::ClassLoader> class_loader, + uint32_t field_idx, + bool is_static) { + ArtField* resolved = nullptr; + Thread* self = is_static ? Thread::Current() : nullptr; + const DexFile& dex_file = *dex_cache->GetDexFile(); + + resolved = is_static ? mirror::Class::FindStaticField(self, klass, dex_cache, field_idx) + : klass->FindInstanceField(dex_cache, field_idx); + + if (resolved == nullptr) { + const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx); + const char* name = dex_file.GetFieldName(field_id); + const char* type = dex_file.GetFieldTypeDescriptor(field_id); + resolved = is_static ? mirror::Class::FindStaticField(self, klass, name, type) + : klass->FindInstanceField(name, type); + } + + if (resolved != nullptr && + hiddenapi::GetMemberAction( + resolved, class_loader, dex_cache, hiddenapi::kLinking) == hiddenapi::kDeny) { + resolved = nullptr; + } + + if (resolved != nullptr) { + dex_cache->SetResolvedField(field_idx, resolved, image_pointer_size_); + } + + return resolved; +} + +ArtField* ClassLinker::FindResolvedFieldJLS(ObjPtr<mirror::Class> klass, + ObjPtr<mirror::DexCache> dex_cache, + ObjPtr<mirror::ClassLoader> class_loader, + uint32_t field_idx) { + ArtField* resolved = nullptr; + Thread* self = Thread::Current(); + const DexFile& dex_file = *dex_cache->GetDexFile(); + const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx); + + const char* name = dex_file.GetFieldName(field_id); + const char* type = dex_file.GetFieldTypeDescriptor(field_id); resolved = mirror::Class::FindField(self, klass, name, type); + if (resolved != nullptr && hiddenapi::GetMemberAction( - resolved, class_loader.Get(), dex_cache.Get(), hiddenapi::kLinking) == hiddenapi::kDeny) { + resolved, class_loader, dex_cache, hiddenapi::kLinking) == hiddenapi::kDeny) { resolved = nullptr; } + if (resolved != nullptr) { dex_cache->SetResolvedField(field_idx, resolved, image_pointer_size_); - } else { - ThrowNoSuchFieldError("", klass, type, name); } + return resolved; } diff --git a/runtime/class_linker.h b/runtime/class_linker.h index e935d1dfb8..60cff9ee37 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -392,6 +392,27 @@ class ClassLinker { REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_); + // Find a field with a given ID from the DexFile associated with the given DexCache + // and ClassLoader, storing the result in DexCache. The declaring class is assumed + // to have been already resolved into `klass`. The `is_static` argument is used to + // determine if we are resolving a static or non-static field. + ArtField* FindResolvedField(ObjPtr<mirror::Class> klass, + ObjPtr<mirror::DexCache> dex_cache, + ObjPtr<mirror::ClassLoader> class_loader, + uint32_t field_idx, + bool is_static) + REQUIRES_SHARED(Locks::mutator_lock_); + + // Find a field with a given ID from the DexFile associated with the given DexCache + // and ClassLoader, storing the result in DexCache. The declaring class is assumed + // to have been already resolved into `klass`. No is_static argument is provided + // so that Java field resolution semantics are followed. + ArtField* FindResolvedFieldJLS(ObjPtr<mirror::Class> klass, + ObjPtr<mirror::DexCache> dex_cache, + ObjPtr<mirror::ClassLoader> class_loader, + uint32_t field_idx) + REQUIRES_SHARED(Locks::mutator_lock_); + // Resolve a method type with a given ID from the DexFile associated with a given DexCache // and ClassLoader, storing the result in the DexCache. ObjPtr<mirror::MethodType> ResolveMethodType(Thread* self, |