diff options
| -rw-r--r-- | libdexfile/dex/dex_file-inl.h | 13 | ||||
| -rw-r--r-- | libdexfile/dex/dex_file.h | 3 | ||||
| -rw-r--r-- | runtime/class_linker.cc | 13 | ||||
| -rw-r--r-- | runtime/mirror/class.cc | 161 | ||||
| -rw-r--r-- | runtime/mirror/class.h | 4 | ||||
| -rw-r--r-- | runtime/mirror/var_handle_test.cc | 4 | ||||
| -rw-r--r-- | runtime/thread.cc | 12 | ||||
| -rw-r--r-- | runtime/transaction_test.cc | 13 | ||||
| -rw-r--r-- | runtime/well_known_classes.cc | 64 | ||||
| -rw-r--r-- | runtime/well_known_classes.h | 1 |
10 files changed, 219 insertions, 69 deletions
diff --git a/libdexfile/dex/dex_file-inl.h b/libdexfile/dex/dex_file-inl.h index 0e1fb68a66..182ef0e0a8 100644 --- a/libdexfile/dex/dex_file-inl.h +++ b/libdexfile/dex/dex_file-inl.h @@ -98,15 +98,28 @@ inline const char* DexFile::GetTypeDescriptor(const dex::TypeId& type_id) const return StringDataByIdx(type_id.descriptor_idx_); } +inline std::string_view DexFile::GetTypeDescriptorView(const dex::TypeId& type_id) const { + return StringViewByIdx(type_id.descriptor_idx_); +} + inline const char* DexFile::GetFieldTypeDescriptor(const dex::FieldId& field_id) const { const dex::TypeId& type_id = GetTypeId(field_id.type_idx_); return GetTypeDescriptor(type_id); } +inline std::string_view DexFile::GetFieldTypeDescriptorView(const dex::FieldId& field_id) const { + const dex::TypeId& type_id = GetTypeId(field_id.type_idx_); + return GetTypeDescriptorView(type_id); +} + inline const char* DexFile::GetFieldName(const dex::FieldId& field_id) const { return StringDataByIdx(field_id.name_idx_); } +inline std::string_view DexFile::GetFieldNameView(const dex::FieldId& field_id) const { + return StringViewByIdx(field_id.name_idx_); +} + inline const char* DexFile::GetMethodDeclaringClassDescriptor(const dex::MethodId& method_id) const { const dex::TypeId& type_id = GetTypeId(method_id.class_idx_); diff --git a/libdexfile/dex/dex_file.h b/libdexfile/dex/dex_file.h index e3027fc95f..fb7fdedc01 100644 --- a/libdexfile/dex/dex_file.h +++ b/libdexfile/dex/dex_file.h @@ -307,6 +307,7 @@ class DexFile { // Returns the type descriptor string of a type id. const char* GetTypeDescriptor(const dex::TypeId& type_id) const; + std::string_view GetTypeDescriptorView(const dex::TypeId& type_id) const; // Looks up a type for the given string index const dex::TypeId* FindTypeId(dex::StringIndex string_idx) const; @@ -354,9 +355,11 @@ class DexFile { // Returns the class descriptor string of a field id. const char* GetFieldTypeDescriptor(const dex::FieldId& field_id) const; + std::string_view GetFieldTypeDescriptorView(const dex::FieldId& field_id) const; // Returns the name of a field id. const char* GetFieldName(const dex::FieldId& field_id) const; + std::string_view GetFieldNameView(const dex::FieldId& field_id) const; // Returns the number of method identifiers in the .dex file. size_t NumMethodIds() const { diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index e21a004e33..1134e20369 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -9359,14 +9359,8 @@ 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 dex::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); + ArtField* resolved = mirror::Class::FindField(self, klass, dex_cache, field_idx); if (resolved != nullptr && hiddenapi::ShouldDenyAccessToMember(resolved, @@ -10043,10 +10037,7 @@ ObjPtr<mirror::ClassLoader> ClassLinker::CreateWellKnownClassLoader( // Make a pretend boot-classpath. // TODO: Should we scan the image? ArtField* const parent_field = - mirror::Class::FindField(self, - h_class_loader->GetClass(), - "parent", - "Ljava/lang/ClassLoader;"); + jni::DecodeArtField(WellKnownClasses::java_lang_ClassLoader_parent); DCHECK(parent_field != nullptr); if (parent_loader.Get() == nullptr) { ScopedObjectAccessUnchecked soa(self); diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index 3f9d41c659..6543435720 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -900,27 +900,28 @@ ArtMethod* Class::FindClassInitializer(PointerSize pointer_size) { } // Custom binary search to avoid double comparisons from std::binary_search. -static ArtField* FindFieldByNameAndType(LengthPrefixedArray<ArtField>* fields, +static ArtField* FindFieldByNameAndType(const DexFile& dex_file, + LengthPrefixedArray<ArtField>* fields, std::string_view name, std::string_view type) REQUIRES_SHARED(Locks::mutator_lock_) { - if (fields == nullptr) { - return nullptr; - } + DCHECK(fields != nullptr); size_t low = 0; size_t high = fields->size(); ArtField* ret = nullptr; while (low < high) { size_t mid = (low + high) / 2; ArtField& field = fields->At(mid); + DCHECK(field.GetDexFile() == &dex_file); + const dex::FieldId& field_id = dex_file.GetFieldId(field.GetDexFieldIndex()); // Fields are sorted by class, then name, then type descriptor. This is verified in dex file // verifier. There can be multiple fields with the same in the same class name due to proguard. // Note: std::string_view::compare() uses lexicographical comparison and treats the `char` as // unsigned; for modified-UTF-8 without embedded nulls this is consistent with the // CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues() ordering. - int result = std::string_view(field.GetName()).compare(name); + int result = dex_file.GetFieldNameView(field_id).compare(name); if (result == 0) { - result = std::string_view(field.GetTypeDescriptor()).compare(type); + result = dex_file.GetFieldTypeDescriptorView(field_id).compare(type); } if (result < 0) { low = mid + 1; @@ -946,7 +947,12 @@ static ArtField* FindFieldByNameAndType(LengthPrefixedArray<ArtField>* fields, ArtField* Class::FindDeclaredInstanceField(std::string_view name, std::string_view type) { // Binary search by name. Interfaces are not relevant because they can't contain instance fields. - return FindFieldByNameAndType(GetIFieldsPtr(), name, type); + LengthPrefixedArray<ArtField>* ifields = GetIFieldsPtr(); + if (ifields == nullptr) { + return nullptr; + } + DCHECK(!IsProxyClass()); + return FindFieldByNameAndType(GetDexFile(), ifields, name, type); } ArtField* Class::FindDeclaredInstanceField(ObjPtr<DexCache> dex_cache, uint32_t dex_field_idx) { @@ -986,7 +992,28 @@ ArtField* Class::FindInstanceField(ObjPtr<DexCache> dex_cache, uint32_t dex_fiel ArtField* Class::FindDeclaredStaticField(std::string_view name, std::string_view type) { DCHECK(!type.empty()); - return FindFieldByNameAndType(GetSFieldsPtr(), name, type); + LengthPrefixedArray<ArtField>* sfields = GetSFieldsPtr(); + if (sfields == nullptr) { + return nullptr; + } + if (UNLIKELY(IsProxyClass())) { + // Proxy fields do not have appropriate dex field indexes required by + // `FindFieldByNameAndType()`. However, each proxy class has exactly + // the same artificial fields created by the `ClassLinker`. + DCHECK_EQ(sfields->size(), 2u); + DCHECK_EQ(strcmp(sfields->At(0).GetName(), "interfaces"), 0); + DCHECK_EQ(strcmp(sfields->At(0).GetTypeDescriptor(), "[Ljava/lang/Class;"), 0); + DCHECK_EQ(strcmp(sfields->At(1).GetName(), "throws"), 0); + DCHECK_EQ(strcmp(sfields->At(1).GetTypeDescriptor(), "[[Ljava/lang/Class;"), 0); + if (name == "interfaces") { + return (type == "[Ljava/lang/Class;") ? &sfields->At(0) : nullptr; + } else if (name == "throws") { + return (type == "[[Ljava/lang/Class;") ? &sfields->At(1) : nullptr; + } else { + return nullptr; + } + } + return FindFieldByNameAndType(GetDexFile(), sfields, name, type); } ArtField* Class::FindDeclaredStaticField(ObjPtr<DexCache> dex_cache, uint32_t dex_field_idx) { @@ -1051,30 +1078,124 @@ ArtField* Class::FindStaticField(Thread* self, return nullptr; } +// Find a field using the JLS field resolution order +FLATTEN ArtField* Class::FindField(Thread* self, ObjPtr<Class> klass, - std::string_view name, - std::string_view type) { - // Find a field using the JLS field resolution order - for (ObjPtr<Class> k = klass; k != nullptr; k = k->GetSuperClass()) { - // Is the field in this class? - ArtField* f = k->FindDeclaredInstanceField(name, type); + ObjPtr<mirror::DexCache> dex_cache, + uint32_t field_idx) { + // FIXME: Hijacking a proxy class by a custom class loader can break this assumption. + DCHECK(!klass->IsProxyClass()); + + // First try to find a declared field by `field_idx` if we have a `dex_cache` match. + ObjPtr<DexCache> klass_dex_cache = klass->GetDexCache(); + if (klass_dex_cache == dex_cache) { + // Lookup is always performed in the class referenced by the FieldId. + DCHECK_EQ(klass->dex_type_idx_, + klass_dex_cache->GetDexFile()->GetFieldId(field_idx).class_idx_.index_); + ArtField* f = klass->FindDeclaredInstanceField(klass_dex_cache, field_idx); + if (f == nullptr) { + f = klass->FindDeclaredStaticField(klass_dex_cache, field_idx); + } if (f != nullptr) { return f; } - f = k->FindDeclaredStaticField(name, type); + } + + const DexFile& dex_file = *dex_cache->GetDexFile(); + const dex::FieldId& field_id = dex_file.GetFieldId(field_idx); + + std::string_view name; // Do not touch the dex file string data until actually needed. + std::string_view type; + auto ensure_name_and_type_initialized = [&]() REQUIRES_SHARED(Locks::mutator_lock_) { + if (name.empty()) { + name = dex_file.GetFieldNameView(field_id); + type = dex_file.GetFieldTypeDescriptorView(field_id); + } + }; + + auto search_direct_interfaces = [&](ObjPtr<mirror::Class> k) + REQUIRES_SHARED(Locks::mutator_lock_) { + // TODO: The `FindStaticField()` performs a recursive search and it's possible to + // construct interface hierarchies that make the time complexity exponential in depth. + // Rewrite this with a `HashSet<mirror::Class*>` to mark classes we have already + // searched for the field, so that we call `FindDeclaredStaticField()` only once + // on each interface. And use a work queue to avoid unlimited recursion depth. + // TODO: Once we call `FindDeclaredStaticField()` directly, use search by indexes + // instead of strings if the interface's dex cache matches `dex_cache`. This shall + // allow delaying the `ensure_name_and_type_initialized()` call further. + uint32_t num_interfaces = k->NumDirectInterfaces(); + if (num_interfaces != 0u) { + ensure_name_and_type_initialized(); + for (uint32_t i = 0; i != num_interfaces; ++i) { + ObjPtr<Class> interface = GetDirectInterface(self, k, i); + DCHECK(interface != nullptr); + ArtField* f = FindStaticField(self, interface, name, type); + if (f != nullptr) { + return f; + } + } + } + return static_cast<ArtField*>(nullptr); + }; + + // If we had a dex cache mismatch, search declared fields by name and type. + if (klass_dex_cache != dex_cache && + (klass->GetIFieldsPtr() != nullptr || klass->GetSFieldsPtr() != nullptr)) { + ensure_name_and_type_initialized(); + ArtField* f = klass->FindDeclaredInstanceField(name, type); + if (f == nullptr) { + f = klass->FindDeclaredStaticField(name, type); + } if (f != nullptr) { return f; } - // Is this field in any of this class' interfaces? - for (uint32_t i = 0, num_interfaces = k->NumDirectInterfaces(); i != num_interfaces; ++i) { - ObjPtr<Class> interface = GetDirectInterface(self, k, i); - DCHECK(interface != nullptr); - f = FindStaticField(self, interface, name, type); + } + + // Search direct interfaces. + { + ArtField* f = search_direct_interfaces(klass); + if (f != nullptr) { + return f; + } + } + + // Continue searching in superclasses. + for (ObjPtr<Class> k = klass->GetSuperClass(); k != nullptr; k = k->GetSuperClass()) { + // Is the field in this class? + ObjPtr<DexCache> k_dex_cache = k->GetDexCache(); + if (k_dex_cache == dex_cache) { + // Matching dex_cache. We cannot compare the `field_idx` anymore because + // the type index differs, so compare the name index and type index. + for (ArtField& field : k->GetIFields()) { + const dex::FieldId& other_field_id = dex_file.GetFieldId(field.GetDexFieldIndex()); + if (other_field_id.name_idx_ == field_id.name_idx_ && + other_field_id.type_idx_ == field_id.type_idx_) { + return &field; + } + } + for (ArtField& field : k->GetSFields()) { + const dex::FieldId& other_field_id = dex_file.GetFieldId(field.GetDexFieldIndex()); + if (other_field_id.name_idx_ == field_id.name_idx_ && + other_field_id.type_idx_ == field_id.type_idx_) { + return &field; + } + } + } else if (k->GetIFieldsPtr() != nullptr || k->GetSFieldsPtr() != nullptr) { + ensure_name_and_type_initialized(); + ArtField* f = k->FindDeclaredInstanceField(name, type); + if (f == nullptr) { + f = k->FindDeclaredStaticField(name, type); + } if (f != nullptr) { return f; } } + // Is this field in any of this class' interfaces? + ArtField* f = search_direct_interfaces(k); + if (f != nullptr) { + return f; + } } return nullptr; } diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index cc2924e3c1..aff98cabe2 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -1094,8 +1094,8 @@ class MANAGED Class final : public Object { // Find a static or instance field using the JLS resolution order static ArtField* FindField(Thread* self, ObjPtr<Class> klass, - std::string_view name, - std::string_view type) + ObjPtr<mirror::DexCache> dex_cache, + uint32_t field_idx) REQUIRES_SHARED(Locks::mutator_lock_); // Finds the given instance field in this class or a superclass. diff --git a/runtime/mirror/var_handle_test.cc b/runtime/mirror/var_handle_test.cc index 5e763ddf92..c32c702a91 100644 --- a/runtime/mirror/var_handle_test.cc +++ b/runtime/mirror/var_handle_test.cc @@ -278,7 +278,7 @@ TEST_F(VarHandleTest, InstanceFieldVarHandle) { ScopedObjectAccess soa(self); ObjPtr<Object> i = BoxPrimitive(Primitive::kPrimInt, JValue::FromPrimitive<int32_t>(37)); - ArtField* value = mirror::Class::FindField(self, i->GetClass(), "value", "I"); + ArtField* value = i->GetClass()->FindDeclaredInstanceField("value", "I"); int32_t mask = AccessModesBitMask(VarHandle::AccessMode::kGet, VarHandle::AccessMode::kGetAndSet, VarHandle::AccessMode::kGetAndBitwiseXor); @@ -481,7 +481,7 @@ TEST_F(VarHandleTest, StaticFieldVarHandle) { ScopedObjectAccess soa(self); ObjPtr<Object> i = BoxPrimitive(Primitive::kPrimInt, JValue::FromPrimitive<int32_t>(37)); - ArtField* value = mirror::Class::FindField(self, i->GetClass(), "MIN_VALUE", "I"); + ArtField* value = i->GetClass()->FindDeclaredStaticField("MIN_VALUE", "I"); int32_t mask = AccessModesBitMask(VarHandle::AccessMode::kSet, VarHandle::AccessMode::kGetOpaque, VarHandle::AccessMode::kGetAndBitwiseAndRelease); diff --git a/runtime/thread.cc b/runtime/thread.cc index 16a5f93be4..61a751c14f 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -3158,14 +3158,14 @@ jobjectArray Thread::CreateAnnotatedStackTrace(const ScopedObjectAccessAlreadyRu return nullptr; } - ArtField* stack_trace_element_field = h_aste_class->FindField( - soa.Self(), h_aste_class.Get(), "stackTraceElement", "Ljava/lang/StackTraceElement;"); + ArtField* stack_trace_element_field = + h_aste_class->FindDeclaredInstanceField("stackTraceElement", "Ljava/lang/StackTraceElement;"); DCHECK(stack_trace_element_field != nullptr); - ArtField* held_locks_field = h_aste_class->FindField( - soa.Self(), h_aste_class.Get(), "heldLocks", "[Ljava/lang/Object;"); + ArtField* held_locks_field = + h_aste_class->FindDeclaredInstanceField("heldLocks", "[Ljava/lang/Object;"); DCHECK(held_locks_field != nullptr); - ArtField* blocked_on_field = h_aste_class->FindField( - soa.Self(), h_aste_class.Get(), "blockedOn", "Ljava/lang/Object;"); + ArtField* blocked_on_field = + h_aste_class->FindDeclaredInstanceField("blockedOn", "Ljava/lang/Object;"); DCHECK(blocked_on_field != nullptr); int32_t length = static_cast<int32_t>(dumper.stack_trace_elements_.size()); diff --git a/runtime/transaction_test.cc b/runtime/transaction_test.cc index ee7c59135c..f606d0276c 100644 --- a/runtime/transaction_test.cc +++ b/runtime/transaction_test.cc @@ -627,15 +627,13 @@ TEST_F(TransactionTest, Constraints) { class_linker_->FindClass(soa.Self(), "Ljava/lang/Boolean;", class_loader)); ASSERT_TRUE(boolean_class != nullptr); ASSERT_TRUE(heap->ObjectIsInBootImageSpace(boolean_class.Get())); - ArtField* true_field = - mirror::Class::FindField(soa.Self(), boolean_class.Get(), "TRUE", "Ljava/lang/Boolean;"); + ArtField* true_field = boolean_class->FindDeclaredStaticField("TRUE", "Ljava/lang/Boolean;"); ASSERT_TRUE(true_field != nullptr); ASSERT_TRUE(true_field->IsStatic()); Handle<mirror::Object> true_value = hs.NewHandle(true_field->GetObject(boolean_class.Get())); ASSERT_TRUE(true_value != nullptr); ASSERT_TRUE(heap->ObjectIsInBootImageSpace(true_value.Get())); - ArtField* value_field = - mirror::Class::FindField(soa.Self(), boolean_class.Get(), "value", "Z"); + ArtField* value_field = boolean_class->FindDeclaredInstanceField("value", "Z"); ASSERT_TRUE(value_field != nullptr); ASSERT_FALSE(value_field->IsStatic()); @@ -643,8 +641,7 @@ TEST_F(TransactionTest, Constraints) { class_linker_->FindClass(soa.Self(), "LTransaction$StaticFieldClass;", class_loader))); ASSERT_TRUE(static_field_class != nullptr); ASSERT_FALSE(heap->ObjectIsInBootImageSpace(static_field_class.Get())); - ArtField* int_field = - mirror::Class::FindField(soa.Self(), static_field_class.Get(), "intField", "I"); + ArtField* int_field = static_field_class->FindDeclaredStaticField("intField", "I"); ASSERT_TRUE(int_field != nullptr); Handle<mirror::Class> static_fields_test_class(hs.NewHandle( @@ -652,7 +649,7 @@ TEST_F(TransactionTest, Constraints) { ASSERT_TRUE(static_fields_test_class != nullptr); ASSERT_FALSE(heap->ObjectIsInBootImageSpace(static_fields_test_class.Get())); ArtField* static_fields_test_int_field = - mirror::Class::FindField(soa.Self(), static_fields_test_class.Get(), "intField", "I"); + static_fields_test_class->FindDeclaredStaticField("intField", "I"); ASSERT_TRUE(static_fields_test_int_field != nullptr); Handle<mirror::Class> instance_fields_test_class(hs.NewHandle( @@ -660,7 +657,7 @@ TEST_F(TransactionTest, Constraints) { ASSERT_TRUE(instance_fields_test_class != nullptr); ASSERT_FALSE(heap->ObjectIsInBootImageSpace(instance_fields_test_class.Get())); ArtField* instance_fields_test_int_field = - mirror::Class::FindField(soa.Self(), instance_fields_test_class.Get(), "intField", "I"); + instance_fields_test_class->FindDeclaredInstanceField("intField", "I"); ASSERT_TRUE(instance_fields_test_int_field != nullptr); Handle<mirror::Object> instance_fields_test_object = hs.NewHandle( instance_fields_test_class->Alloc(soa.Self(), heap->GetCurrentAllocator())); diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc index 3b3a1a3f9f..8414aa40b4 100644 --- a/runtime/well_known_classes.cc +++ b/runtime/well_known_classes.cc @@ -136,6 +136,7 @@ jfieldID WellKnownClasses::dalvik_system_DexPathList_dexElements; jfieldID WellKnownClasses::dalvik_system_DexPathList__Element_dexFile; jfieldID WellKnownClasses::dalvik_system_VMRuntime_nonSdkApiUsageConsumer; jfieldID WellKnownClasses::java_io_FileDescriptor_descriptor; +jfieldID WellKnownClasses::java_lang_ClassLoader_parent; jfieldID WellKnownClasses::java_lang_Thread_parkBlocker; jfieldID WellKnownClasses::java_lang_Thread_daemon; jfieldID WellKnownClasses::java_lang_Thread_group; @@ -429,30 +430,46 @@ void WellKnownClasses::InitFieldsAndMethodsOnly(JNIEnv* env) { ScopedLocalRef<jclass> java_io_FileDescriptor(env, env->FindClass("java/io/FileDescriptor")); java_io_FileDescriptor_descriptor = CacheField(env, java_io_FileDescriptor.get(), false, "descriptor", "I"); - java_lang_Thread_parkBlocker = CacheField(env, java_lang_Thread, false, "parkBlocker", "Ljava/lang/Object;"); + java_lang_ClassLoader_parent = + CacheField(env, java_lang_ClassLoader, false, "parent", "Ljava/lang/ClassLoader;"); + java_lang_Thread_parkBlocker = + CacheField(env, java_lang_Thread, false, "parkBlocker", "Ljava/lang/Object;"); java_lang_Thread_daemon = CacheField(env, java_lang_Thread, false, "daemon", "Z"); - java_lang_Thread_group = CacheField(env, java_lang_Thread, false, "group", "Ljava/lang/ThreadGroup;"); + java_lang_Thread_group = + CacheField(env, java_lang_Thread, false, "group", "Ljava/lang/ThreadGroup;"); java_lang_Thread_lock = CacheField(env, java_lang_Thread, false, "lock", "Ljava/lang/Object;"); java_lang_Thread_name = CacheField(env, java_lang_Thread, false, "name", "Ljava/lang/String;"); java_lang_Thread_priority = CacheField(env, java_lang_Thread, false, "priority", "I"); java_lang_Thread_nativePeer = CacheField(env, java_lang_Thread, false, "nativePeer", "J"); java_lang_Thread_systemDaemon = CacheField(env, java_lang_Thread, false, "systemDaemon", "Z"); - java_lang_Thread_unparkedBeforeStart = CacheField(env, java_lang_Thread, false, "unparkedBeforeStart", "Z"); - java_lang_ThreadGroup_groups = CacheField(env, java_lang_ThreadGroup, false, "groups", "[Ljava/lang/ThreadGroup;"); + java_lang_Thread_unparkedBeforeStart = + CacheField(env, java_lang_Thread, false, "unparkedBeforeStart", "Z"); + java_lang_ThreadGroup_groups = + CacheField(env, java_lang_ThreadGroup, false, "groups", "[Ljava/lang/ThreadGroup;"); java_lang_ThreadGroup_ngroups = CacheField(env, java_lang_ThreadGroup, false, "ngroups", "I"); - java_lang_ThreadGroup_mainThreadGroup = CacheField(env, java_lang_ThreadGroup, true, "mainThreadGroup", "Ljava/lang/ThreadGroup;"); - java_lang_ThreadGroup_name = CacheField(env, java_lang_ThreadGroup, false, "name", "Ljava/lang/String;"); - java_lang_ThreadGroup_parent = CacheField(env, java_lang_ThreadGroup, false, "parent", "Ljava/lang/ThreadGroup;"); - java_lang_ThreadGroup_systemThreadGroup = CacheField(env, java_lang_ThreadGroup, true, "systemThreadGroup", "Ljava/lang/ThreadGroup;"); - java_lang_Throwable_cause = CacheField(env, java_lang_Throwable, false, "cause", "Ljava/lang/Throwable;"); - java_lang_Throwable_detailMessage = CacheField(env, java_lang_Throwable, false, "detailMessage", "Ljava/lang/String;"); - java_lang_Throwable_stackTrace = CacheField(env, java_lang_Throwable, false, "stackTrace", "[Ljava/lang/StackTraceElement;"); - java_lang_Throwable_stackState = CacheField(env, java_lang_Throwable, false, "backtrace", "Ljava/lang/Object;"); - java_lang_Throwable_suppressedExceptions = CacheField(env, java_lang_Throwable, false, "suppressedExceptions", "Ljava/util/List;"); + java_lang_ThreadGroup_mainThreadGroup = + CacheField(env, java_lang_ThreadGroup, true, "mainThreadGroup", "Ljava/lang/ThreadGroup;"); + java_lang_ThreadGroup_name = + CacheField(env, java_lang_ThreadGroup, false, "name", "Ljava/lang/String;"); + java_lang_ThreadGroup_parent = + CacheField(env, java_lang_ThreadGroup, false, "parent", "Ljava/lang/ThreadGroup;"); + java_lang_ThreadGroup_systemThreadGroup = + CacheField(env, java_lang_ThreadGroup, true, "systemThreadGroup", "Ljava/lang/ThreadGroup;"); + java_lang_Throwable_cause = + CacheField(env, java_lang_Throwable, false, "cause", "Ljava/lang/Throwable;"); + java_lang_Throwable_detailMessage = + CacheField(env, java_lang_Throwable, false, "detailMessage", "Ljava/lang/String;"); + java_lang_Throwable_stackTrace = + CacheField(env, java_lang_Throwable, false, "stackTrace", "[Ljava/lang/StackTraceElement;"); + java_lang_Throwable_stackState = + CacheField(env, java_lang_Throwable, false, "backtrace", "Ljava/lang/Object;"); + java_lang_Throwable_suppressedExceptions = + CacheField(env, java_lang_Throwable, false, "suppressedExceptions", "Ljava/util/List;"); java_nio_Buffer_address = CacheField(env, java_nio_Buffer, false, "address", "J"); java_nio_Buffer_capacity = CacheField(env, java_nio_Buffer, false, "capacity", "I"); - java_nio_Buffer_elementSizeShift = CacheField(env, java_nio_Buffer, false, "_elementSizeShift", "I"); + java_nio_Buffer_elementSizeShift = + CacheField(env, java_nio_Buffer, false, "_elementSizeShift", "I"); java_nio_Buffer_limit = CacheField(env, java_nio_Buffer, false, "limit", "I"); java_nio_Buffer_position = CacheField(env, java_nio_Buffer, false, "position", "I"); @@ -461,12 +478,18 @@ void WellKnownClasses::InitFieldsAndMethodsOnly(JNIEnv* env) { java_nio_ByteBuffer_isReadOnly = CacheField(env, java_nio_ByteBuffer, false, "isReadOnly", "Z"); java_nio_ByteBuffer_limit = CacheField(env, java_nio_ByteBuffer, false, "limit", "I"); java_nio_ByteBuffer_offset = CacheField(env, java_nio_ByteBuffer, false, "offset", "I"); - java_util_Collections_EMPTY_LIST = CacheField(env, java_util_Collections, true, "EMPTY_LIST", "Ljava/util/List;"); - libcore_util_EmptyArray_STACK_TRACE_ELEMENT = CacheField(env, libcore_util_EmptyArray, true, "STACK_TRACE_ELEMENT", "[Ljava/lang/StackTraceElement;"); - org_apache_harmony_dalvik_ddmc_Chunk_data = CacheField(env, org_apache_harmony_dalvik_ddmc_Chunk, false, "data", "[B"); - org_apache_harmony_dalvik_ddmc_Chunk_length = CacheField(env, org_apache_harmony_dalvik_ddmc_Chunk, false, "length", "I"); - org_apache_harmony_dalvik_ddmc_Chunk_offset = CacheField(env, org_apache_harmony_dalvik_ddmc_Chunk, false, "offset", "I"); - org_apache_harmony_dalvik_ddmc_Chunk_type = CacheField(env, org_apache_harmony_dalvik_ddmc_Chunk, false, "type", "I"); + java_util_Collections_EMPTY_LIST = + CacheField(env, java_util_Collections, true, "EMPTY_LIST", "Ljava/util/List;"); + libcore_util_EmptyArray_STACK_TRACE_ELEMENT = CacheField( + env, libcore_util_EmptyArray, true, "STACK_TRACE_ELEMENT", "[Ljava/lang/StackTraceElement;"); + org_apache_harmony_dalvik_ddmc_Chunk_data = + CacheField(env, org_apache_harmony_dalvik_ddmc_Chunk, false, "data", "[B"); + org_apache_harmony_dalvik_ddmc_Chunk_length = + CacheField(env, org_apache_harmony_dalvik_ddmc_Chunk, false, "length", "I"); + org_apache_harmony_dalvik_ddmc_Chunk_offset = + CacheField(env, org_apache_harmony_dalvik_ddmc_Chunk, false, "offset", "I"); + org_apache_harmony_dalvik_ddmc_Chunk_type = + CacheField(env, org_apache_harmony_dalvik_ddmc_Chunk, false, "type", "I"); java_lang_Boolean_valueOf = CachePrimitiveBoxingMethod(env, 'Z', "java/lang/Boolean"); java_lang_Byte_valueOf = CachePrimitiveBoxingMethod(env, 'B', "java/lang/Byte"); @@ -602,6 +625,7 @@ void WellKnownClasses::Clear() { dalvik_system_DexPathList_dexElements = nullptr; dalvik_system_DexPathList__Element_dexFile = nullptr; dalvik_system_VMRuntime_nonSdkApiUsageConsumer = nullptr; + java_lang_ClassLoader_parent = nullptr; java_lang_Thread_parkBlocker = nullptr; java_lang_Thread_daemon = nullptr; java_lang_Thread_group = nullptr; diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h index b2e01aed55..434d041c9f 100644 --- a/runtime/well_known_classes.h +++ b/runtime/well_known_classes.h @@ -149,6 +149,7 @@ struct WellKnownClasses { static jfieldID dalvik_system_DexPathList__Element_dexFile; static jfieldID dalvik_system_VMRuntime_nonSdkApiUsageConsumer; static jfieldID java_io_FileDescriptor_descriptor; + static jfieldID java_lang_ClassLoader_parent; static jfieldID java_lang_Thread_parkBlocker; static jfieldID java_lang_Thread_daemon; static jfieldID java_lang_Thread_group; |