diff options
-rw-r--r-- | runtime/class_linker.cc | 30 | ||||
-rw-r--r-- | runtime/class_linker.h | 6 | ||||
-rw-r--r-- | runtime/dex_file.cc | 971 | ||||
-rw-r--r-- | runtime/dex_file.h | 194 | ||||
-rw-r--r-- | runtime/mirror/class.cc | 10 | ||||
-rw-r--r-- | runtime/mirror/class.h | 3 | ||||
-rw-r--r-- | runtime/native/java_lang_Class.cc | 45 | ||||
-rw-r--r-- | runtime/native/java_lang_reflect_Constructor.cc | 57 | ||||
-rw-r--r-- | runtime/native/java_lang_reflect_Field.cc | 52 | ||||
-rw-r--r-- | runtime/native/java_lang_reflect_Method.cc | 111 | ||||
-rw-r--r-- | runtime/well_known_classes.cc | 10 | ||||
-rw-r--r-- | runtime/well_known_classes.h | 5 |
12 files changed, 1421 insertions, 73 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index b547d079cd..dc273d8fe0 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -5546,6 +5546,36 @@ ArtMethod* ClassLinker::ResolveMethod(const DexFile& dex_file, uint32_t method_i } } +ArtMethod* ClassLinker::ResolveMethodWithoutInvokeType(const DexFile& dex_file, + uint32_t method_idx, + Handle<mirror::DexCache> dex_cache, + Handle<mirror::ClassLoader> class_loader) { + ArtMethod* resolved = dex_cache->GetResolvedMethod(method_idx, image_pointer_size_); + if (resolved != nullptr && !resolved->IsRuntimeMethod()) { + DCHECK(resolved->GetDeclaringClassUnchecked() != nullptr) << resolved->GetDexMethodIndex(); + return resolved; + } + // Fail, get the declaring class. + const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx); + mirror::Class* klass = ResolveType(dex_file, method_id.class_idx_, dex_cache, class_loader); + if (klass == nullptr) { + Thread::Current()->AssertPendingException(); + return nullptr; + } + if (klass->IsInterface()) { + LOG(FATAL) << "ResolveAmbiguousMethod: unexpected method in interface: " << PrettyClass(klass); + return nullptr; + } + + // Search both direct and virtual methods + resolved = klass->FindDirectMethod(dex_cache.Get(), method_idx, image_pointer_size_); + if (resolved == nullptr) { + resolved = klass->FindVirtualMethod(dex_cache.Get(), method_idx, image_pointer_size_); + } + + return resolved; +} + ArtField* ClassLinker::ResolveField(const DexFile& dex_file, uint32_t field_idx, Handle<mirror::DexCache> dex_cache, Handle<mirror::ClassLoader> class_loader, bool is_static) { diff --git a/runtime/class_linker.h b/runtime/class_linker.h index 7243a25a48..fbf4035842 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -229,6 +229,12 @@ class ClassLinker { SHARED_REQUIRES(Locks::mutator_lock_); ArtMethod* ResolveMethod(Thread* self, uint32_t method_idx, ArtMethod* referrer, InvokeType type) SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!dex_lock_, !Roles::uninterruptible_); + ArtMethod* ResolveMethodWithoutInvokeType(const DexFile& dex_file, + uint32_t method_idx, + Handle<mirror::DexCache> dex_cache, + Handle<mirror::ClassLoader> class_loader) + SHARED_REQUIRES(Locks::mutator_lock_) + REQUIRES(!dex_lock_, !Roles::uninterruptible_); ArtField* GetResolvedField(uint32_t field_idx, mirror::Class* field_declaring_class) SHARED_REQUIRES(Locks::mutator_lock_); diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc index 52590a5970..213f25dfdb 100644 --- a/runtime/dex_file.cc +++ b/runtime/dex_file.cc @@ -32,13 +32,16 @@ #include "base/hash_map.h" #include "base/logging.h" #include "base/stringprintf.h" -#include "class_linker.h" +#include "class_linker-inl.h" #include "dex_file-inl.h" #include "dex_file_verifier.h" #include "globals.h" #include "leb128.h" +#include "mirror/field.h" +#include "mirror/method.h" #include "mirror/string.h" #include "os.h" +#include "reflection.h" #include "safe_map.h" #include "handle_scope-inl.h" #include "thread.h" @@ -1044,6 +1047,918 @@ std::string DexFile::GetDexCanonicalLocation(const char* dex_location) { } } +// Read a signed integer. "zwidth" is the zero-based byte count. +static int32_t ReadSignedInt(const uint8_t* ptr, int zwidth) { + int32_t val = 0; + for (int i = zwidth; i >= 0; --i) { + val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24); + } + val >>= (3 - zwidth) * 8; + return val; +} + +// Read an unsigned integer. "zwidth" is the zero-based byte count, +// "fill_on_right" indicates which side we want to zero-fill from. +static uint32_t ReadUnsignedInt(const uint8_t* ptr, int zwidth, bool fill_on_right) { + uint32_t val = 0; + for (int i = zwidth; i >= 0; --i) { + val = (val >> 8) | (((uint32_t)*ptr++) << 24); + } + if (!fill_on_right) { + val >>= (3 - zwidth) * 8; + } + return val; +} + +// Read a signed long. "zwidth" is the zero-based byte count. +static int64_t ReadSignedLong(const uint8_t* ptr, int zwidth) { + int64_t val = 0; + for (int i = zwidth; i >= 0; --i) { + val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56); + } + val >>= (7 - zwidth) * 8; + return val; +} + +// Read an unsigned long. "zwidth" is the zero-based byte count, +// "fill_on_right" indicates which side we want to zero-fill from. +static uint64_t ReadUnsignedLong(const uint8_t* ptr, int zwidth, bool fill_on_right) { + uint64_t val = 0; + for (int i = zwidth; i >= 0; --i) { + val = (val >> 8) | (((uint64_t)*ptr++) << 56); + } + if (!fill_on_right) { + val >>= (7 - zwidth) * 8; + } + return val; +} + +const DexFile::AnnotationSetItem* DexFile::FindAnnotationSetForField(ArtField* field) const { + mirror::Class* klass = field->GetDeclaringClass(); + const AnnotationsDirectoryItem* annotations_dir = GetAnnotationsDirectory(*klass->GetClassDef()); + if (annotations_dir == nullptr) { + return nullptr; + } + const FieldAnnotationsItem* field_annotations = GetFieldAnnotations(annotations_dir); + if (field_annotations == nullptr) { + return nullptr; + } + uint32_t field_index = field->GetDexFieldIndex(); + uint32_t field_count = annotations_dir->fields_size_; + for (uint32_t i = 0; i < field_count; ++i) { + if (field_annotations[i].field_idx_ == field_index) { + return GetFieldAnnotationSetItem(field_annotations[i]); + } + } + return nullptr; +} + +mirror::Object* DexFile::GetAnnotationForField(ArtField* field, + Handle<mirror::Class> annotation_class) const { + const AnnotationSetItem* annotation_set = FindAnnotationSetForField(field); + if (annotation_set == nullptr) { + return nullptr; + } + StackHandleScope<1> hs(Thread::Current()); + Handle<mirror::Class> field_class(hs.NewHandle(field->GetDeclaringClass())); + return GetAnnotationObjectFromAnnotationSet( + field_class, annotation_set, kDexVisibilityRuntime, annotation_class); +} + +mirror::ObjectArray<mirror::Object>* DexFile::GetAnnotationsForField(ArtField* field) const { + const AnnotationSetItem* annotation_set = FindAnnotationSetForField(field); + StackHandleScope<1> hs(Thread::Current()); + Handle<mirror::Class> field_class(hs.NewHandle(field->GetDeclaringClass())); + return ProcessAnnotationSet(field_class, annotation_set, kDexVisibilityRuntime); +} + +mirror::ObjectArray<mirror::Object>* DexFile::GetSignatureAnnotationForField(ArtField* field) + const { + const AnnotationSetItem* annotation_set = FindAnnotationSetForField(field); + if (annotation_set == nullptr) { + return nullptr; + } + StackHandleScope<1> hs(Thread::Current()); + Handle<mirror::Class> field_class(hs.NewHandle(field->GetDeclaringClass())); + return GetSignatureValue(field_class, annotation_set); +} + +bool DexFile::IsFieldAnnotationPresent(ArtField* field, Handle<mirror::Class> annotation_class) + const { + const AnnotationSetItem* annotation_set = FindAnnotationSetForField(field); + if (annotation_set == nullptr) { + return false; + } + StackHandleScope<1> hs(Thread::Current()); + Handle<mirror::Class> field_class(hs.NewHandle(field->GetDeclaringClass())); + const AnnotationItem* annotation_item = GetAnnotationItemFromAnnotationSet( + field_class, annotation_set, kDexVisibilityRuntime, annotation_class); + return annotation_item != nullptr; +} + +const DexFile::AnnotationSetItem* DexFile::FindAnnotationSetForMethod(ArtMethod* method) const { + mirror::Class* klass = method->GetDeclaringClass(); + const AnnotationsDirectoryItem* annotations_dir = GetAnnotationsDirectory(*klass->GetClassDef()); + if (annotations_dir == nullptr) { + return nullptr; + } + const MethodAnnotationsItem* method_annotations = GetMethodAnnotations(annotations_dir); + if (method_annotations == nullptr) { + return nullptr; + } + uint32_t method_index = method->GetDexMethodIndex(); + uint32_t method_count = annotations_dir->methods_size_; + for (uint32_t i = 0; i < method_count; ++i) { + if (method_annotations[i].method_idx_ == method_index) { + return GetMethodAnnotationSetItem(method_annotations[i]); + } + } + return nullptr; +} + +const DexFile::ParameterAnnotationsItem* DexFile::FindAnnotationsItemForMethod(ArtMethod* method) + const { + mirror::Class* klass = method->GetDeclaringClass(); + const AnnotationsDirectoryItem* annotations_dir = GetAnnotationsDirectory(*klass->GetClassDef()); + if (annotations_dir == nullptr) { + return nullptr; + } + const ParameterAnnotationsItem* parameter_annotations = GetParameterAnnotations(annotations_dir); + if (parameter_annotations == nullptr) { + return nullptr; + } + uint32_t method_index = method->GetDexMethodIndex(); + uint32_t parameter_count = annotations_dir->parameters_size_; + for (uint32_t i = 0; i < parameter_count; ++i) { + if (parameter_annotations[i].method_idx_ == method_index) { + return ¶meter_annotations[i]; + } + } + return nullptr; +} + +mirror::Object* DexFile::GetAnnotationDefaultValue(ArtMethod* method) const { + mirror::Class* klass = method->GetDeclaringClass(); + const AnnotationsDirectoryItem* annotations_dir = GetAnnotationsDirectory(*klass->GetClassDef()); + if (annotations_dir == nullptr) { + return nullptr; + } + const AnnotationSetItem* annotation_set = GetClassAnnotationSet(annotations_dir); + if (annotation_set == nullptr) { + return nullptr; + } + const AnnotationItem* annotation_item = SearchAnnotationSet(annotation_set, + "Ldalvik/annotation/AnnotationDefault;", kDexVisibilitySystem); + if (annotation_item == nullptr) { + return nullptr; + } + const uint8_t* annotation = SearchEncodedAnnotation(annotation_item->annotation_, "value"); + if (annotation == nullptr) { + return nullptr; + } + uint8_t header_byte = *(annotation++); + if ((header_byte & kDexAnnotationValueTypeMask) != kDexAnnotationAnnotation) { + return nullptr; + } + annotation = SearchEncodedAnnotation(annotation, method->GetName()); + if (annotation == nullptr) { + return nullptr; + } + AnnotationValue annotation_value; + StackHandleScope<2> hs(Thread::Current()); + Handle<mirror::Class> h_klass(hs.NewHandle(klass)); + Handle<mirror::Class> return_type(hs.NewHandle(method->GetReturnType())); + if (!ProcessAnnotationValue(h_klass, &annotation, &annotation_value, return_type, kAllObjects)) { + return nullptr; + } + return annotation_value.value_.GetL(); +} + +mirror::Object* DexFile::GetAnnotationForMethod(ArtMethod* method, + Handle<mirror::Class> annotation_class) const { + const AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method); + if (annotation_set == nullptr) { + return nullptr; + } + StackHandleScope<1> hs(Thread::Current()); + Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass())); + return GetAnnotationObjectFromAnnotationSet(method_class, annotation_set, + kDexVisibilityRuntime, annotation_class); +} + +mirror::ObjectArray<mirror::Object>* DexFile::GetAnnotationsForMethod(ArtMethod* method) const { + const AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method); + StackHandleScope<1> hs(Thread::Current()); + Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass())); + return ProcessAnnotationSet(method_class, annotation_set, kDexVisibilityRuntime); +} + +mirror::ObjectArray<mirror::Object>* DexFile::GetExceptionTypesForMethod(ArtMethod* method) const { + const AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method); + if (annotation_set == nullptr) { + return nullptr; + } + StackHandleScope<1> hs(Thread::Current()); + Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass())); + return GetThrowsValue(method_class, annotation_set); +} + +mirror::ObjectArray<mirror::Object>* DexFile::GetParameterAnnotations(ArtMethod* method) const { + const ParameterAnnotationsItem* parameter_annotations = FindAnnotationsItemForMethod(method); + if (parameter_annotations == nullptr) { + return nullptr; + } + const AnnotationSetRefList* set_ref_list = + GetParameterAnnotationSetRefList(parameter_annotations); + if (set_ref_list == nullptr) { + return nullptr; + } + uint32_t size = set_ref_list->size_; + StackHandleScope<1> hs(Thread::Current()); + Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass())); + return ProcessAnnotationSetRefList(method_class, set_ref_list, size); +} + +bool DexFile::IsMethodAnnotationPresent(ArtMethod* method, Handle<mirror::Class> annotation_class) + const { + const AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method); + if (annotation_set == nullptr) { + return false; + } + StackHandleScope<1> hs(Thread::Current()); + Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass())); + const AnnotationItem* annotation_item = GetAnnotationItemFromAnnotationSet( + method_class, annotation_set, kDexVisibilityRuntime, annotation_class); + return (annotation_item != nullptr); +} + +const DexFile::AnnotationSetItem* DexFile::FindAnnotationSetForClass(Handle<mirror::Class> klass) + const { + const AnnotationsDirectoryItem* annotations_dir = GetAnnotationsDirectory(*klass->GetClassDef()); + if (annotations_dir == nullptr) { + return nullptr; + } + return GetClassAnnotationSet(annotations_dir); +} + +mirror::Object* DexFile::GetAnnotationForClass(Handle<mirror::Class> klass, + Handle<mirror::Class> annotation_class) const { + const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); + if (annotation_set == nullptr) { + return nullptr; + } + return GetAnnotationObjectFromAnnotationSet(klass, annotation_set, kDexVisibilityRuntime, + annotation_class); +} + +mirror::ObjectArray<mirror::Object>* DexFile::GetAnnotationsForClass(Handle<mirror::Class> klass) + const { + const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); + return ProcessAnnotationSet(klass, annotation_set, kDexVisibilityRuntime); +} + +bool DexFile::IsClassAnnotationPresent(Handle<mirror::Class> klass, + Handle<mirror::Class> annotation_class) const { + const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); + if (annotation_set == nullptr) { + return false; + } + const AnnotationItem* annotation_item = GetAnnotationItemFromAnnotationSet( + klass, annotation_set, kDexVisibilityRuntime, annotation_class); + return (annotation_item != nullptr); +} + +mirror::Object* DexFile::CreateAnnotationMember(Handle<mirror::Class> klass, + Handle<mirror::Class> annotation_class, const uint8_t** annotation) const { + Thread* self = Thread::Current(); + ScopedObjectAccessUnchecked soa(self); + StackHandleScope<5> hs(self); + uint32_t element_name_index = DecodeUnsignedLeb128(annotation); + const char* name = StringDataByIdx(element_name_index); + Handle<mirror::String> string_name( + hs.NewHandle(mirror::String::AllocFromModifiedUtf8(self, name))); + + ArtMethod* annotation_method = + annotation_class->FindDeclaredVirtualMethodByName(name, sizeof(void*)); + if (annotation_method == nullptr) { + return nullptr; + } + Handle<mirror::Class> method_return(hs.NewHandle(annotation_method->GetReturnType())); + + AnnotationValue annotation_value; + if (!ProcessAnnotationValue(klass, annotation, &annotation_value, method_return, kAllObjects)) { + return nullptr; + } + Handle<mirror::Object> value_object(hs.NewHandle(annotation_value.value_.GetL())); + + mirror::Class* annotation_member_class = + WellKnownClasses::ToClass(WellKnownClasses::libcore_reflect_AnnotationMember); + Handle<mirror::Object> new_member(hs.NewHandle(annotation_member_class->AllocObject(self))); + Handle<mirror::Method> method_object( + hs.NewHandle(mirror::Method::CreateFromArtMethod(self, annotation_method))); + + if (new_member.Get() == nullptr || string_name.Get() == nullptr || + method_object.Get() == nullptr || method_return.Get() == nullptr) { + LOG(ERROR) << StringPrintf("Failed creating annotation element (m=%p n=%p a=%p r=%p", + new_member.Get(), string_name.Get(), method_object.Get(), method_return.Get()); + return nullptr; + } + + JValue result; + ArtMethod* annotation_member_init = + soa.DecodeMethod(WellKnownClasses::libcore_reflect_AnnotationMember_init); + uint32_t args[5] = { static_cast<uint32_t>(reinterpret_cast<uintptr_t>(new_member.Get())), + static_cast<uint32_t>(reinterpret_cast<uintptr_t>(string_name.Get())), + static_cast<uint32_t>(reinterpret_cast<uintptr_t>(value_object.Get())), + static_cast<uint32_t>(reinterpret_cast<uintptr_t>(method_return.Get())), + static_cast<uint32_t>(reinterpret_cast<uintptr_t>(method_object.Get())) + }; + annotation_member_init->Invoke(self, args, sizeof(args), &result, "VLLLL"); + if (self->IsExceptionPending()) { + LOG(INFO) << "Exception in AnnotationMember.<init>"; + return nullptr; + } + + return new_member.Get(); +} + +const DexFile::AnnotationItem* DexFile::GetAnnotationItemFromAnnotationSet( + Handle<mirror::Class> klass, const AnnotationSetItem* annotation_set, uint32_t visibility, + Handle<mirror::Class> annotation_class) const { + for (uint32_t i = 0; i < annotation_set->size_; ++i) { + const AnnotationItem* annotation_item = GetAnnotationItem(annotation_set, i); + if (annotation_item->visibility_ != visibility) { + continue; + } + const uint8_t* annotation = annotation_item->annotation_; + uint32_t type_index = DecodeUnsignedLeb128(&annotation); + mirror::Class* resolved_class = Runtime::Current()->GetClassLinker()->ResolveType( + klass->GetDexFile(), type_index, klass.Get()); + if (resolved_class == nullptr) { + std::string temp; + LOG(WARNING) << StringPrintf("Unable to resolve %s annotation class %d", + klass->GetDescriptor(&temp), type_index); + CHECK(Thread::Current()->IsExceptionPending()); + Thread::Current()->ClearException(); + continue; + } + if (resolved_class == annotation_class.Get()) { + return annotation_item; + } + } + + return nullptr; +} + +mirror::Object* DexFile::GetAnnotationObjectFromAnnotationSet(Handle<mirror::Class> klass, + const AnnotationSetItem* annotation_set, uint32_t visibility, + Handle<mirror::Class> annotation_class) const { + const AnnotationItem* annotation_item = + GetAnnotationItemFromAnnotationSet(klass, annotation_set, visibility, annotation_class); + if (annotation_item == nullptr) { + return nullptr; + } + const uint8_t* annotation = annotation_item->annotation_; + return ProcessEncodedAnnotation(klass, &annotation); +} + +mirror::Object* DexFile::GetAnnotationValue(Handle<mirror::Class> klass, + const AnnotationItem* annotation_item, const char* annotation_name, + Handle<mirror::Class> array_class, uint32_t expected_type) const { + const uint8_t* annotation = + SearchEncodedAnnotation(annotation_item->annotation_, annotation_name); + if (annotation == nullptr) { + return nullptr; + } + AnnotationValue annotation_value; + if (!ProcessAnnotationValue(klass, &annotation, &annotation_value, array_class, kAllObjects)) { + return nullptr; + } + if (annotation_value.type_ != expected_type) { + return nullptr; + } + return annotation_value.value_.GetL(); +} + +mirror::ObjectArray<mirror::Object>* DexFile::GetSignatureValue(Handle<mirror::Class> klass, + const AnnotationSetItem* annotation_set) const { + StackHandleScope<1> hs(Thread::Current()); + const AnnotationItem* annotation_item = + SearchAnnotationSet(annotation_set, "Ldalvik/annotation/Signature;", kDexVisibilitySystem); + if (annotation_item == nullptr) { + return nullptr; + } + mirror::Class* string_class = mirror::String::GetJavaLangString(); + Handle<mirror::Class> string_array_class(hs.NewHandle( + Runtime::Current()->GetClassLinker()->FindArrayClass(Thread::Current(), &string_class))); + mirror::Object* obj = + GetAnnotationValue(klass, annotation_item, "value", string_array_class, kDexAnnotationArray); + if (obj == nullptr) { + return nullptr; + } + return obj->AsObjectArray<mirror::Object>(); +} + +mirror::ObjectArray<mirror::Object>* DexFile::GetThrowsValue(Handle<mirror::Class> klass, + const AnnotationSetItem* annotation_set) const { + StackHandleScope<1> hs(Thread::Current()); + const AnnotationItem* annotation_item = + SearchAnnotationSet(annotation_set, "Ldalvik/annotation/Throws;", kDexVisibilitySystem); + if (annotation_item == nullptr) { + return nullptr; + } + mirror::Class* class_class = mirror::Class::GetJavaLangClass(); + Handle<mirror::Class> class_array_class(hs.NewHandle( + Runtime::Current()->GetClassLinker()->FindArrayClass(Thread::Current(), &class_class))); + mirror::Object* obj = + GetAnnotationValue(klass, annotation_item, "value", class_array_class, kDexAnnotationArray); + if (obj == nullptr) { + return nullptr; + } + return obj->AsObjectArray<mirror::Object>(); +} + +mirror::ObjectArray<mirror::Object>* DexFile::ProcessAnnotationSet(Handle<mirror::Class> klass, + const AnnotationSetItem* annotation_set, uint32_t visibility) const { + Thread* self = Thread::Current(); + ScopedObjectAccessUnchecked soa(self); + StackHandleScope<2> hs(self); + Handle<mirror::Class> annotation_array_class(hs.NewHandle( + soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_annotation_Annotation__array))); + if (annotation_set == nullptr) { + return mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_array_class.Get(), 0); + } + + uint32_t size = annotation_set->size_; + Handle<mirror::ObjectArray<mirror::Object>> result(hs.NewHandle( + mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_array_class.Get(), size))); + if (result.Get() == nullptr) { + return nullptr; + } + + uint32_t dest_index = 0; + for (uint32_t i = 0; i < size; ++i) { + const AnnotationItem* annotation_item = GetAnnotationItem(annotation_set, i); + if (annotation_item->visibility_ != visibility) { + continue; + } + const uint8_t* annotation = annotation_item->annotation_; + mirror::Object* annotation_obj = ProcessEncodedAnnotation(klass, &annotation); + if (annotation_obj != nullptr) { + result->SetWithoutChecks<false>(dest_index, annotation_obj); + ++dest_index; + } + } + + if (dest_index == size) { + return result.Get(); + } + + mirror::ObjectArray<mirror::Object>* trimmed_result = + mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_array_class.Get(), dest_index); + for (uint32_t i = 0; i < dest_index; ++i) { + mirror::Object* obj = result->GetWithoutChecks(i); + trimmed_result->SetWithoutChecks<false>(i, obj); + } + + return trimmed_result; +} + +mirror::ObjectArray<mirror::Object>* DexFile::ProcessAnnotationSetRefList( + Handle<mirror::Class> klass, const AnnotationSetRefList* set_ref_list, uint32_t size) const { + Thread* self = Thread::Current(); + ScopedObjectAccessUnchecked soa(self); + StackHandleScope<1> hs(self); + mirror::Class* annotation_array_class = + soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_annotation_Annotation__array); + mirror::Class* annotation_array_array_class = + Runtime::Current()->GetClassLinker()->FindArrayClass(self, &annotation_array_class); + Handle<mirror::ObjectArray<mirror::Object>> annotation_array_array(hs.NewHandle( + mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_array_array_class, size))); + if (annotation_array_array.Get() == nullptr) { + LOG(ERROR) << "Annotation set ref array allocation failed"; + return nullptr; + } + for (uint32_t index = 0; index < size; ++index) { + const AnnotationSetRefItem* set_ref_item = &set_ref_list->list_[index]; + const AnnotationSetItem* set_item = GetSetRefItemItem(set_ref_item); + mirror::Object* annotation_set = ProcessAnnotationSet(klass, set_item, kDexVisibilityRuntime); + if (annotation_set == nullptr) { + return nullptr; + } + annotation_array_array->SetWithoutChecks<false>(index, annotation_set); + } + return annotation_array_array.Get(); +} + +bool DexFile::ProcessAnnotationValue(Handle<mirror::Class> klass, const uint8_t** annotation_ptr, + AnnotationValue* annotation_value, Handle<mirror::Class> array_class, + DexFile::AnnotationResultStyle result_style) const { + Thread* self = Thread::Current(); + mirror::Object* element_object = nullptr; + bool set_object = false; + Primitive::Type primitive_type = Primitive::kPrimVoid; + const uint8_t* annotation = *annotation_ptr; + uint8_t header_byte = *(annotation++); + uint8_t value_type = header_byte & kDexAnnotationValueTypeMask; + uint8_t value_arg = header_byte >> kDexAnnotationValueArgShift; + int32_t width = value_arg + 1; + annotation_value->type_ = value_type; + + switch (value_type) { + case kDexAnnotationByte: + annotation_value->value_.SetB(static_cast<int8_t>(ReadSignedInt(annotation, value_arg))); + primitive_type = Primitive::kPrimByte; + break; + case kDexAnnotationShort: + annotation_value->value_.SetS(static_cast<int16_t>(ReadSignedInt(annotation, value_arg))); + primitive_type = Primitive::kPrimShort; + break; + case kDexAnnotationChar: + annotation_value->value_.SetC(static_cast<uint16_t>(ReadUnsignedInt(annotation, value_arg, + false))); + primitive_type = Primitive::kPrimChar; + break; + case kDexAnnotationInt: + annotation_value->value_.SetI(ReadSignedInt(annotation, value_arg)); + primitive_type = Primitive::kPrimInt; + break; + case kDexAnnotationLong: + annotation_value->value_.SetJ(ReadSignedLong(annotation, value_arg)); + primitive_type = Primitive::kPrimLong; + break; + case kDexAnnotationFloat: + annotation_value->value_.SetI(ReadUnsignedInt(annotation, value_arg, true)); + primitive_type = Primitive::kPrimFloat; + break; + case kDexAnnotationDouble: + annotation_value->value_.SetJ(ReadUnsignedLong(annotation, value_arg, true)); + primitive_type = Primitive::kPrimDouble; + break; + case kDexAnnotationBoolean: + annotation_value->value_.SetZ(value_arg != 0); + primitive_type = Primitive::kPrimBoolean; + width = 0; + break; + case kDexAnnotationString: { + uint32_t index = ReadUnsignedInt(annotation, value_arg, false); + if (result_style == kAllRaw) { + annotation_value->value_.SetI(index); + } else { + StackHandleScope<1> hs(self); + Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache())); + element_object = Runtime::Current()->GetClassLinker()->ResolveString( + klass->GetDexFile(), index, dex_cache); + set_object = true; + if (element_object == nullptr) { + return false; + } + } + break; + } + case kDexAnnotationType: { + uint32_t index = ReadUnsignedInt(annotation, value_arg, false); + if (result_style == kAllRaw) { + annotation_value->value_.SetI(index); + } else { + element_object = Runtime::Current()->GetClassLinker()->ResolveType( + klass->GetDexFile(), index, klass.Get()); + set_object = true; + if (element_object == nullptr) { + self->ClearException(); + const char* msg = StringByTypeIdx(index); + self->ThrowNewException("Ljava/lang/TypeNotPresentException;", msg); + } + } + break; + } + case kDexAnnotationMethod: { + uint32_t index = ReadUnsignedInt(annotation, value_arg, false); + if (result_style == kAllRaw) { + annotation_value->value_.SetI(index); + } else { + StackHandleScope<2> hs(self); + Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache())); + Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader())); + ArtMethod* method = Runtime::Current()->GetClassLinker()->ResolveMethodWithoutInvokeType( + klass->GetDexFile(), index, dex_cache, class_loader); + if (method == nullptr) { + return false; + } + set_object = true; + if (method->IsConstructor()) { + element_object = mirror::Constructor::CreateFromArtMethod(self, method); + } else { + element_object = mirror::Method::CreateFromArtMethod(self, method); + } + if (element_object == nullptr) { + return false; + } + } + break; + } + case kDexAnnotationField: { + uint32_t index = ReadUnsignedInt(annotation, value_arg, false); + if (result_style == kAllRaw) { + annotation_value->value_.SetI(index); + } else { + StackHandleScope<2> hs(self); + Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache())); + Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader())); + ArtField* field = Runtime::Current()->GetClassLinker()->ResolveFieldJLS( + klass->GetDexFile(), index, dex_cache, class_loader); + if (field == nullptr) { + return false; + } + set_object = true; + element_object = mirror::Field::CreateFromArtField(self, field, true); + if (element_object == nullptr) { + return false; + } + } + break; + } + case kDexAnnotationEnum: { + uint32_t index = ReadUnsignedInt(annotation, value_arg, false); + if (result_style == kAllRaw) { + annotation_value->value_.SetI(index); + } else { + StackHandleScope<3> hs(self); + Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache())); + Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader())); + ArtField* enum_field = Runtime::Current()->GetClassLinker()->ResolveField( + klass->GetDexFile(), index, dex_cache, class_loader, true); + Handle<mirror::Class> field_class(hs.NewHandle(enum_field->GetDeclaringClass())); + if (enum_field == nullptr) { + return false; + } else { + Runtime::Current()->GetClassLinker()->EnsureInitialized(self, field_class, true, true); + element_object = enum_field->GetObject(field_class.Get()); + set_object = true; + } + } + break; + } + case kDexAnnotationArray: + if (result_style == kAllRaw || array_class.Get() == nullptr) { + return false; + } else { + ScopedObjectAccessUnchecked soa(self); + StackHandleScope<2> hs(self); + uint32_t size = DecodeUnsignedLeb128(&annotation); + Handle<mirror::Class> component_type(hs.NewHandle(array_class->GetComponentType())); + Handle<mirror::Array> new_array(hs.NewHandle(mirror::Array::Alloc<true>( + self, array_class.Get(), size, array_class->GetComponentSizeShift(), + Runtime::Current()->GetHeap()->GetCurrentAllocator()))); + if (new_array.Get() == nullptr) { + LOG(ERROR) << "Annotation element array allocation failed with size " << size; + return false; + } + AnnotationValue new_annotation_value; + for (uint32_t i = 0; i < size; ++i) { + if (!ProcessAnnotationValue(klass, &annotation, &new_annotation_value, component_type, + kPrimitivesOrObjects)) { + return false; + } + if (!component_type->IsPrimitive()) { + mirror::Object* obj = new_annotation_value.value_.GetL(); + new_array->AsObjectArray<mirror::Object>()->SetWithoutChecks<false>(i, obj); + } else { + switch (new_annotation_value.type_) { + case kDexAnnotationByte: + new_array->AsByteArray()->SetWithoutChecks<false>( + i, new_annotation_value.value_.GetB()); + break; + case kDexAnnotationShort: + new_array->AsShortArray()->SetWithoutChecks<false>( + i, new_annotation_value.value_.GetS()); + break; + case kDexAnnotationChar: + new_array->AsCharArray()->SetWithoutChecks<false>( + i, new_annotation_value.value_.GetC()); + break; + case kDexAnnotationInt: + new_array->AsIntArray()->SetWithoutChecks<false>( + i, new_annotation_value.value_.GetI()); + break; + case kDexAnnotationLong: + new_array->AsLongArray()->SetWithoutChecks<false>( + i, new_annotation_value.value_.GetJ()); + break; + case kDexAnnotationFloat: + new_array->AsFloatArray()->SetWithoutChecks<false>( + i, new_annotation_value.value_.GetF()); + break; + case kDexAnnotationDouble: + new_array->AsDoubleArray()->SetWithoutChecks<false>( + i, new_annotation_value.value_.GetD()); + break; + case kDexAnnotationBoolean: + new_array->AsBooleanArray()->SetWithoutChecks<false>( + i, new_annotation_value.value_.GetZ()); + break; + default: + LOG(FATAL) << "Found invalid annotation value type while building annotation array"; + return false; + } + } + } + element_object = new_array.Get(); + set_object = true; + width = 0; + } + break; + case kDexAnnotationAnnotation: + if (result_style == kAllRaw) { + return false; + } + element_object = ProcessEncodedAnnotation(klass, &annotation); + if (element_object == nullptr) { + return false; + } + set_object = true; + width = 0; + break; + case kDexAnnotationNull: + if (result_style == kAllRaw) { + annotation_value->value_.SetI(0); + } else { + CHECK(element_object == nullptr); + set_object = true; + } + width = 0; + break; + default: + LOG(ERROR) << StringPrintf("Bad annotation element value type 0x%02x", value_type); + return false; + } + + annotation += width; + *annotation_ptr = annotation; + + if (result_style == kAllObjects && primitive_type != Primitive::kPrimVoid) { + element_object = BoxPrimitive(primitive_type, annotation_value->value_); + set_object = true; + } + + if (set_object) { + annotation_value->value_.SetL(element_object); + } + + return true; +} + +mirror::Object* DexFile::ProcessEncodedAnnotation(Handle<mirror::Class> klass, + const uint8_t** annotation) const { + uint32_t type_index = DecodeUnsignedLeb128(annotation); + uint32_t size = DecodeUnsignedLeb128(annotation); + + Thread* self = Thread::Current(); + ScopedObjectAccessUnchecked soa(self); + StackHandleScope<2> hs(self); + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + Handle<mirror::Class> annotation_class(hs.NewHandle( + class_linker->ResolveType(klass->GetDexFile(), type_index, klass.Get()))); + if (annotation_class.Get() == nullptr) { + LOG(INFO) << "Unable to resolve " << PrettyClass(klass.Get()) << " annotation class " + << type_index; + DCHECK(Thread::Current()->IsExceptionPending()); + Thread::Current()->ClearException(); + return nullptr; + } + + mirror::Class* annotation_member_class = + soa.Decode<mirror::Class*>(WellKnownClasses::libcore_reflect_AnnotationMember); + mirror::Class* annotation_member_array_class = + class_linker->FindArrayClass(self, &annotation_member_class); + mirror::ObjectArray<mirror::Object>* element_array = nullptr; + + if (size > 0) { + element_array = + mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_member_array_class, size); + if (element_array == nullptr) { + LOG(ERROR) << "Failed to allocate annotation member array (" << size << " elements)"; + return nullptr; + } + } + + Handle<mirror::ObjectArray<mirror::Object>> h_element_array(hs.NewHandle(element_array)); + for (uint32_t i = 0; i < size; ++i) { + mirror::Object* new_member = CreateAnnotationMember(klass, annotation_class, annotation); + if (new_member == nullptr) { + return nullptr; + } + h_element_array->SetWithoutChecks<false>(i, new_member); + } + + JValue result; + ArtMethod* create_annotation_method = + soa.DecodeMethod(WellKnownClasses::libcore_reflect_AnnotationFactory_createAnnotation); + uint32_t args[2] = { static_cast<uint32_t>(reinterpret_cast<uintptr_t>(annotation_class.Get())), + static_cast<uint32_t>(reinterpret_cast<uintptr_t>(h_element_array.Get())) }; + create_annotation_method->Invoke(self, args, sizeof(args), &result, "LLL"); + if (self->IsExceptionPending()) { + LOG(INFO) << "Exception in AnnotationFactory.createAnnotation"; + return nullptr; + } + + return result.GetL(); +} + +const DexFile::AnnotationItem* DexFile::SearchAnnotationSet(const AnnotationSetItem* annotation_set, + const char* descriptor, uint32_t visibility) const { + const AnnotationItem* result = nullptr; + for (uint32_t i = 0; i < annotation_set->size_; ++i) { + const AnnotationItem* annotation_item = GetAnnotationItem(annotation_set, i); + if (annotation_item->visibility_ != visibility) { + continue; + } + const uint8_t* annotation = annotation_item->annotation_; + uint32_t type_index = DecodeUnsignedLeb128(&annotation); + + if (strcmp(descriptor, StringByTypeIdx(type_index)) == 0) { + result = annotation_item; + break; + } + } + return result; +} + +const uint8_t* DexFile::SearchEncodedAnnotation(const uint8_t* annotation, const char* name) const { + DecodeUnsignedLeb128(&annotation); // unused type_index + uint32_t size = DecodeUnsignedLeb128(&annotation); + + while (size != 0) { + uint32_t element_name_index = DecodeUnsignedLeb128(&annotation); + const char* element_name = GetStringData(GetStringId(element_name_index)); + if (strcmp(name, element_name) == 0) { + return annotation; + } + SkipAnnotationValue(&annotation); + size--; + } + return nullptr; +} + +bool DexFile::SkipAnnotationValue(const uint8_t** annotation_ptr) const { + const uint8_t* annotation = *annotation_ptr; + uint8_t header_byte = *(annotation++); + uint8_t value_type = header_byte & kDexAnnotationValueTypeMask; + uint8_t value_arg = header_byte >> kDexAnnotationValueArgShift; + int32_t width = value_arg + 1; + + switch (value_type) { + case kDexAnnotationByte: + case kDexAnnotationShort: + case kDexAnnotationChar: + case kDexAnnotationInt: + case kDexAnnotationLong: + case kDexAnnotationFloat: + case kDexAnnotationDouble: + case kDexAnnotationString: + case kDexAnnotationType: + case kDexAnnotationMethod: + case kDexAnnotationField: + case kDexAnnotationEnum: + break; + case kDexAnnotationArray: + { + uint32_t size = DecodeUnsignedLeb128(&annotation); + while (size--) { + if (!SkipAnnotationValue(&annotation)) { + return false; + } + } + width = 0; + break; + } + case kDexAnnotationAnnotation: + { + DecodeUnsignedLeb128(&annotation); // unused type_index + uint32_t size = DecodeUnsignedLeb128(&annotation); + while (size--) { + DecodeUnsignedLeb128(&annotation); // unused element_name_index + if (!SkipAnnotationValue(&annotation)) { + return false; + } + } + width = 0; + break; + } + case kDexAnnotationBoolean: + case kDexAnnotationNull: + width = 0; + break; + default: + LOG(FATAL) << StringPrintf("Bad annotation element value byte 0x%02x", value_type); + return false; + } + + annotation += width; + *annotation_ptr = annotation; + return true; +} + std::ostream& operator<<(std::ostream& os, const DexFile& dex_file) { os << StringPrintf("[DexFile: %s dex-checksum=%08x location-checksum=%08x %p-%p]", dex_file.GetLocation().c_str(), @@ -1127,60 +2042,6 @@ void ClassDataItemIterator::ReadClassDataMethod() { } } -// Read a signed integer. "zwidth" is the zero-based byte count. -static int32_t ReadSignedInt(const uint8_t* ptr, int zwidth) { - int32_t val = 0; - for (int i = zwidth; i >= 0; --i) { - val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24); - } - val >>= (3 - zwidth) * 8; - return val; -} - -// Read an unsigned integer. "zwidth" is the zero-based byte count, -// "fill_on_right" indicates which side we want to zero-fill from. -static uint32_t ReadUnsignedInt(const uint8_t* ptr, int zwidth, bool fill_on_right) { - uint32_t val = 0; - if (!fill_on_right) { - for (int i = zwidth; i >= 0; --i) { - val = (val >> 8) | (((uint32_t)*ptr++) << 24); - } - val >>= (3 - zwidth) * 8; - } else { - for (int i = zwidth; i >= 0; --i) { - val = (val >> 8) | (((uint32_t)*ptr++) << 24); - } - } - return val; -} - -// Read a signed long. "zwidth" is the zero-based byte count. -static int64_t ReadSignedLong(const uint8_t* ptr, int zwidth) { - int64_t val = 0; - for (int i = zwidth; i >= 0; --i) { - val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56); - } - val >>= (7 - zwidth) * 8; - return val; -} - -// Read an unsigned long. "zwidth" is the zero-based byte count, -// "fill_on_right" indicates which side we want to zero-fill from. -static uint64_t ReadUnsignedLong(const uint8_t* ptr, int zwidth, bool fill_on_right) { - uint64_t val = 0; - if (!fill_on_right) { - for (int i = zwidth; i >= 0; --i) { - val = (val >> 8) | (((uint64_t)*ptr++) << 56); - } - val >>= (7 - zwidth) * 8; - } else { - for (int i = zwidth; i >= 0; --i) { - val = (val >> 8) | (((uint64_t)*ptr++) << 56); - } - } - return val; -} - EncodedStaticFieldValueIterator::EncodedStaticFieldValueIterator( const DexFile& dex_file, Handle<mirror::DexCache>* dex_cache, Handle<mirror::ClassLoader>* class_loader, ClassLinker* linker, diff --git a/runtime/dex_file.h b/runtime/dex_file.h index fc805f88d5..89283213a8 100644 --- a/runtime/dex_file.h +++ b/runtime/dex_file.h @@ -28,6 +28,8 @@ #include "globals.h" #include "invoke_type.h" #include "jni.h" +#include "jvalue.h" +#include "mirror/object_array.h" #include "modifiers.h" #include "utf.h" @@ -384,6 +386,17 @@ class DexFile { DISALLOW_COPY_AND_ASSIGN(AnnotationItem); }; + struct AnnotationValue { + JValue value_; + uint8_t type_; + }; + + enum AnnotationResultStyle { // private + kAllObjects, + kPrimitivesOrObjects, + kAllRaw + }; + // Returns the checksum of a file for comparison with GetLocationChecksum(). // For .dex files, this is the header checksum. // For zip files, this is the classes.dex zip entry CRC32 checksum. @@ -817,6 +830,187 @@ class DexFile { static bool LineNumForPcCb(void* context, uint32_t address, uint32_t line_num); + const AnnotationsDirectoryItem* GetAnnotationsDirectory(const ClassDef& class_def) const { + if (class_def.annotations_off_ == 0) { + return nullptr; + } else { + return reinterpret_cast<const AnnotationsDirectoryItem*>(begin_ + class_def.annotations_off_); + } + } + + const AnnotationSetItem* GetClassAnnotationSet(const AnnotationsDirectoryItem* anno_dir) const { + if (anno_dir->class_annotations_off_ == 0) { + return nullptr; + } else { + return reinterpret_cast<const AnnotationSetItem*>(begin_ + anno_dir->class_annotations_off_); + } + } + + const FieldAnnotationsItem* GetFieldAnnotations(const AnnotationsDirectoryItem* anno_dir) const { + if (anno_dir->fields_size_ == 0) { + return nullptr; + } else { + return reinterpret_cast<const FieldAnnotationsItem*>(&anno_dir[1]); + } + } + + const MethodAnnotationsItem* GetMethodAnnotations(const AnnotationsDirectoryItem* anno_dir) + const { + if (anno_dir->methods_size_ == 0) { + return nullptr; + } else { + // Skip past the header and field annotations. + const uint8_t* addr = reinterpret_cast<const uint8_t*>(&anno_dir[1]); + addr += anno_dir->fields_size_ * sizeof(FieldAnnotationsItem); + return reinterpret_cast<const MethodAnnotationsItem*>(addr); + } + } + + const ParameterAnnotationsItem* GetParameterAnnotations(const AnnotationsDirectoryItem* anno_dir) + const { + if (anno_dir->parameters_size_ == 0) { + return nullptr; + } else { + // Skip past the header, field annotations, and method annotations. + const uint8_t* addr = reinterpret_cast<const uint8_t*>(&anno_dir[1]); + addr += anno_dir->fields_size_ * sizeof(FieldAnnotationsItem); + addr += anno_dir->methods_size_ * sizeof(MethodAnnotationsItem); + return reinterpret_cast<const ParameterAnnotationsItem*>(addr); + } + } + + const AnnotationSetItem* GetFieldAnnotationSetItem(const FieldAnnotationsItem& anno_item) const { + uint32_t offset = anno_item.annotations_off_; + if (offset == 0) { + return nullptr; + } else { + return reinterpret_cast<const AnnotationSetItem*>(begin_ + offset); + } + } + + const AnnotationSetItem* GetMethodAnnotationSetItem(const MethodAnnotationsItem& anno_item) + const { + uint32_t offset = anno_item.annotations_off_; + if (offset == 0) { + return nullptr; + } else { + return reinterpret_cast<const AnnotationSetItem*>(begin_ + offset); + } + } + + const AnnotationSetRefList* GetParameterAnnotationSetRefList( + const ParameterAnnotationsItem* anno_item) const { + uint32_t offset = anno_item->annotations_off_; + if (offset == 0) { + return nullptr; + } + return reinterpret_cast<const AnnotationSetRefList*>(begin_ + offset); + } + + const AnnotationItem* GetAnnotationItem(const AnnotationSetItem* set_item, uint32_t index) const { + DCHECK_LE(index, set_item->size_); + uint32_t offset = set_item->entries_[index]; + if (offset == 0) { + return nullptr; + } else { + return reinterpret_cast<const AnnotationItem*>(begin_ + offset); + } + } + + const AnnotationSetItem* GetSetRefItemItem(const AnnotationSetRefItem* anno_item) const { + uint32_t offset = anno_item->annotations_off_; + if (offset == 0) { + return nullptr; + } + return reinterpret_cast<const AnnotationSetItem*>(begin_ + offset); + } + + const AnnotationSetItem* FindAnnotationSetForField(ArtField* field) const + SHARED_REQUIRES(Locks::mutator_lock_); + mirror::Object* GetAnnotationForField(ArtField* field, Handle<mirror::Class> annotation_class) + const SHARED_REQUIRES(Locks::mutator_lock_); + mirror::ObjectArray<mirror::Object>* GetAnnotationsForField(ArtField* field) const + SHARED_REQUIRES(Locks::mutator_lock_); + mirror::ObjectArray<mirror::Object>* GetSignatureAnnotationForField(ArtField* field) const + SHARED_REQUIRES(Locks::mutator_lock_); + bool IsFieldAnnotationPresent(ArtField* field, Handle<mirror::Class> annotation_class) const + SHARED_REQUIRES(Locks::mutator_lock_); + + const AnnotationSetItem* FindAnnotationSetForMethod(ArtMethod* method) const + SHARED_REQUIRES(Locks::mutator_lock_); + const ParameterAnnotationsItem* FindAnnotationsItemForMethod(ArtMethod* method) const + SHARED_REQUIRES(Locks::mutator_lock_); + mirror::Object* GetAnnotationDefaultValue(ArtMethod* method) const + SHARED_REQUIRES(Locks::mutator_lock_); + mirror::Object* GetAnnotationForMethod(ArtMethod* method, Handle<mirror::Class> annotation_class) + const SHARED_REQUIRES(Locks::mutator_lock_); + mirror::ObjectArray<mirror::Object>* GetAnnotationsForMethod(ArtMethod* method) const + SHARED_REQUIRES(Locks::mutator_lock_); + mirror::ObjectArray<mirror::Object>* GetExceptionTypesForMethod(ArtMethod* method) const + SHARED_REQUIRES(Locks::mutator_lock_); + mirror::ObjectArray<mirror::Object>* GetParameterAnnotations(ArtMethod* method) const + SHARED_REQUIRES(Locks::mutator_lock_); + bool IsMethodAnnotationPresent(ArtMethod* method, Handle<mirror::Class> annotation_class) const + SHARED_REQUIRES(Locks::mutator_lock_); + + const AnnotationSetItem* FindAnnotationSetForClass(Handle<mirror::Class> klass) const + SHARED_REQUIRES(Locks::mutator_lock_); + mirror::Object* GetAnnotationForClass(Handle<mirror::Class> klass, + Handle<mirror::Class> annotation_class) const + SHARED_REQUIRES(Locks::mutator_lock_); + mirror::ObjectArray<mirror::Object>* GetAnnotationsForClass(Handle<mirror::Class> klass) const + SHARED_REQUIRES(Locks::mutator_lock_); + bool IsClassAnnotationPresent(Handle<mirror::Class> klass, Handle<mirror::Class> annotation_class) + const SHARED_REQUIRES(Locks::mutator_lock_); + + mirror::Object* CreateAnnotationMember(Handle<mirror::Class> klass, + Handle<mirror::Class> annotation_class, + const uint8_t** annotation) const + SHARED_REQUIRES(Locks::mutator_lock_); + const AnnotationItem* GetAnnotationItemFromAnnotationSet(Handle<mirror::Class> klass, + const AnnotationSetItem* annotation_set, + uint32_t visibility, + Handle<mirror::Class> annotation_class) + const SHARED_REQUIRES(Locks::mutator_lock_); + mirror::Object* GetAnnotationObjectFromAnnotationSet(Handle<mirror::Class> klass, + const AnnotationSetItem* annotation_set, + uint32_t visibility, + Handle<mirror::Class> annotation_class) const + SHARED_REQUIRES(Locks::mutator_lock_); + mirror::Object* GetAnnotationValue(Handle<mirror::Class> klass, + const AnnotationItem* annotation_item, + const char* annotation_name, + Handle<mirror::Class> array_class, + uint32_t expected_type) const + SHARED_REQUIRES(Locks::mutator_lock_); + mirror::ObjectArray<mirror::Object>* GetSignatureValue(Handle<mirror::Class> klass, + const AnnotationSetItem* annotation_set) + const SHARED_REQUIRES(Locks::mutator_lock_); + mirror::ObjectArray<mirror::Object>* GetThrowsValue(Handle<mirror::Class> klass, + const AnnotationSetItem* annotation_set) const + SHARED_REQUIRES(Locks::mutator_lock_); + mirror::ObjectArray<mirror::Object>* ProcessAnnotationSet(Handle<mirror::Class> klass, + const AnnotationSetItem* annotation_set, + uint32_t visibility) const + SHARED_REQUIRES(Locks::mutator_lock_); + mirror::ObjectArray<mirror::Object>* ProcessAnnotationSetRefList(Handle<mirror::Class> klass, + const AnnotationSetRefList* set_ref_list, uint32_t size) const + SHARED_REQUIRES(Locks::mutator_lock_); + bool ProcessAnnotationValue(Handle<mirror::Class> klass, const uint8_t** annotation_ptr, + AnnotationValue* annotation_value, Handle<mirror::Class> return_class, + DexFile::AnnotationResultStyle result_style) const + SHARED_REQUIRES(Locks::mutator_lock_); + mirror::Object* ProcessEncodedAnnotation(Handle<mirror::Class> klass, + const uint8_t** annotation) const + SHARED_REQUIRES(Locks::mutator_lock_); + const AnnotationItem* SearchAnnotationSet(const AnnotationSetItem* annotation_set, + const char* descriptor, uint32_t visibility) const + SHARED_REQUIRES(Locks::mutator_lock_); + const uint8_t* SearchEncodedAnnotation(const uint8_t* annotation, const char* name) const + SHARED_REQUIRES(Locks::mutator_lock_); + bool SkipAnnotationValue(const uint8_t** annotation_ptr) const + SHARED_REQUIRES(Locks::mutator_lock_); + // Debug info opcodes and constants enum { DBG_END_SEQUENCE = 0x00, diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index 3bea978974..bed26b2813 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -511,6 +511,16 @@ ArtMethod* Class::FindDeclaredVirtualMethod(const DexCache* dex_cache, uint32_t return nullptr; } +ArtMethod* Class::FindDeclaredVirtualMethodByName(const StringPiece& name, size_t pointer_size) { + for (auto& method : GetVirtualMethods(pointer_size)) { + ArtMethod* const np_method = method.GetInterfaceMethodIfProxy(pointer_size); + if (name == np_method->GetName()) { + return &method; + } + } + return nullptr; +} + ArtMethod* Class::FindVirtualMethod( const StringPiece& name, const StringPiece& signature, size_t pointer_size) { for (Class* klass = this; klass != nullptr; klass = klass->GetSuperClass()) { diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index cbcb517001..ef257ae457 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -831,6 +831,9 @@ class MANAGED Class FINAL : public Object { size_t pointer_size) SHARED_REQUIRES(Locks::mutator_lock_); + ArtMethod* FindDeclaredVirtualMethodByName(const StringPiece& name, size_t pointer_size) + SHARED_REQUIRES(Locks::mutator_lock_); + ArtMethod* FindVirtualMethod(const StringPiece& name, const StringPiece& signature, size_t pointer_size) SHARED_REQUIRES(Locks::mutator_lock_); diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc index c337e91cf8..7e464e9a76 100644 --- a/runtime/native/java_lang_Class.cc +++ b/runtime/native/java_lang_Class.cc @@ -426,6 +426,45 @@ static jobjectArray Class_getDeclaredMethodsUnchecked(JNIEnv* env, jobject javaT return soa.AddLocalReference<jobjectArray>(ret.Get()); } +static jobject Class_getDeclaredAnnotation(JNIEnv* env, jobject javaThis, jclass annotationType) { + ScopedFastNativeObjectAccess soa(env); + StackHandleScope<2> hs(soa.Self()); + Handle<mirror::Class> klass(hs.NewHandle(DecodeClass(soa, javaThis))); + if (klass->IsProxyClass()) { + return nullptr; + } + Handle<mirror::Class> annotation_class(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType))); + return soa.AddLocalReference<jobject>( + klass->GetDexFile().GetAnnotationForClass(klass, annotation_class)); +} + +static jobjectArray Class_getDeclaredAnnotations(JNIEnv* env, jobject javaThis) { + ScopedFastNativeObjectAccess soa(env); + StackHandleScope<1> hs(soa.Self()); + Handle<mirror::Class> klass(hs.NewHandle(DecodeClass(soa, javaThis))); + if (klass->IsProxyClass()) { + // Return an empty array instead of a null pointer. + mirror::Class* annotation_array_class = + soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_annotation_Annotation__array); + mirror::ObjectArray<mirror::Object>* empty_array = + mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), annotation_array_class, 0); + return soa.AddLocalReference<jobjectArray>(empty_array); + } + return soa.AddLocalReference<jobjectArray>(klass->GetDexFile().GetAnnotationsForClass(klass)); +} + +static jboolean Class_isDeclaredAnnotationPresent(JNIEnv* env, jobject javaThis, + jclass annotationType) { + ScopedFastNativeObjectAccess soa(env); + StackHandleScope<2> hs(soa.Self()); + Handle<mirror::Class> klass(hs.NewHandle(DecodeClass(soa, javaThis))); + if (klass->IsProxyClass()) { + return false; + } + Handle<mirror::Class> annotation_class(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType))); + return klass->GetDexFile().IsClassAnnotationPresent(klass, annotation_class); +} + static jobject Class_newInstance(JNIEnv* env, jobject javaThis) { ScopedFastNativeObjectAccess soa(env); StackHandleScope<4> hs(soa.Self()); @@ -508,6 +547,9 @@ static jobject Class_newInstance(JNIEnv* env, jobject javaThis) { static JNINativeMethod gMethods[] = { NATIVE_METHOD(Class, classForName, "!(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"), + NATIVE_METHOD(Class, getDeclaredAnnotation, + "!(Ljava/lang/Class;)Ljava/lang/annotation/Annotation;"), + NATIVE_METHOD(Class, getDeclaredAnnotations, "!()[Ljava/lang/annotation/Annotation;"), NATIVE_METHOD(Class, getDeclaredConstructorInternal, "!([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;"), NATIVE_METHOD(Class, getDeclaredConstructorsInternal, "!(Z)[Ljava/lang/reflect/Constructor;"), @@ -518,10 +560,11 @@ static JNINativeMethod gMethods[] = { NATIVE_METHOD(Class, getDeclaredMethodInternal, "!(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;"), NATIVE_METHOD(Class, getDeclaredMethodsUnchecked, - "!(Z)[Ljava/lang/reflect/Method;"), + "!(Z)[Ljava/lang/reflect/Method;"), NATIVE_METHOD(Class, getNameNative, "!()Ljava/lang/String;"), NATIVE_METHOD(Class, getProxyInterfaces, "!()[Ljava/lang/Class;"), NATIVE_METHOD(Class, getPublicDeclaredFields, "!()[Ljava/lang/reflect/Field;"), + NATIVE_METHOD(Class, isDeclaredAnnotationPresent, "!(Ljava/lang/Class;)Z"), NATIVE_METHOD(Class, newInstance, "!()Ljava/lang/Object;"), }; diff --git a/runtime/native/java_lang_reflect_Constructor.cc b/runtime/native/java_lang_reflect_Constructor.cc index 93ba84a8c3..b4b77e737d 100644 --- a/runtime/native/java_lang_reflect_Constructor.cc +++ b/runtime/native/java_lang_reflect_Constructor.cc @@ -18,6 +18,7 @@ #include "art_method-inl.h" #include "class_linker.h" +#include "class_linker-inl.h" #include "jni_internal.h" #include "mirror/class-inl.h" #include "mirror/method.h" @@ -28,6 +29,55 @@ namespace art { +static jobject Constructor_getAnnotationNative(JNIEnv* env, jobject javaMethod, + jclass annotationType) { + ScopedFastNativeObjectAccess soa(env); + StackHandleScope<1> hs(soa.Self()); + ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod); + Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType))); + return soa.AddLocalReference<jobject>( + method->GetDexFile()->GetAnnotationForMethod(method, klass)); +} + +static jobjectArray Constructor_getDeclaredAnnotations(JNIEnv* env, jobject javaMethod) { + ScopedFastNativeObjectAccess soa(env); + ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod); + return soa.AddLocalReference<jobjectArray>(method->GetDexFile()->GetAnnotationsForMethod(method)); +} + +static jobjectArray Constructor_getExceptionTypes(JNIEnv* env, jobject javaMethod) { + ScopedFastNativeObjectAccess soa(env); + ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod); + mirror::ObjectArray<mirror::Object>* result_array = + method->GetDexFile()->GetExceptionTypesForMethod(method); + if (result_array == nullptr) { + // Return an empty array instead of a null pointer. + mirror::Class* class_class = mirror::Class::GetJavaLangClass(); + mirror::Class* class_array_class = + Runtime::Current()->GetClassLinker()->FindArrayClass(soa.Self(), &class_class); + mirror::ObjectArray<mirror::Object>* empty_array = + mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), class_array_class, 0); + return soa.AddLocalReference<jobjectArray>(empty_array); + } else { + return soa.AddLocalReference<jobjectArray>(result_array); + } +} + +static jobjectArray Constructor_getParameterAnnotationsNative(JNIEnv* env, jobject javaMethod) { + ScopedFastNativeObjectAccess soa(env); + ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod); + return soa.AddLocalReference<jobjectArray>(method->GetDexFile()->GetParameterAnnotations(method)); +} + +static jboolean Constructor_isAnnotationPresentNative(JNIEnv* env, jobject javaMethod, + jclass annotationType) { + ScopedFastNativeObjectAccess soa(env); + StackHandleScope<1> hs(soa.Self()); + ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod); + Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType))); + return method->GetDexFile()->IsMethodAnnotationPresent(method, klass); +} + /* * We can also safely assume the constructor isn't associated * with an interface, array, or primitive class. If this is coming from @@ -82,6 +132,13 @@ static jobject Constructor_newInstance(JNIEnv* env, jobject javaMethod, jobjectA } static JNINativeMethod gMethods[] = { + NATIVE_METHOD(Constructor, getAnnotationNative, + "!(Ljava/lang/Class;)Ljava/lang/annotation/Annotation;"), + NATIVE_METHOD(Constructor, getDeclaredAnnotations, "!()[Ljava/lang/annotation/Annotation;"), + NATIVE_METHOD(Constructor, getExceptionTypes, "!()[Ljava/lang/Class;"), + NATIVE_METHOD(Constructor, getParameterAnnotationsNative, + "!()[[Ljava/lang/annotation/Annotation;"), + NATIVE_METHOD(Constructor, isAnnotationPresentNative, "!(Ljava/lang/Class;)Z"), NATIVE_METHOD(Constructor, newInstance, "!([Ljava/lang/Object;)Ljava/lang/Object;"), }; diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc index 5bbb0dc45f..aac800a35a 100644 --- a/runtime/native/java_lang_reflect_Field.cc +++ b/runtime/native/java_lang_reflect_Field.cc @@ -415,16 +415,68 @@ static void Field_setShort(JNIEnv* env, jobject javaField, jobject javaObj, jsho SetPrimitiveField<Primitive::kPrimShort>(env, javaField, javaObj, value); } +static jobject Field_getAnnotationNative(JNIEnv* env, jobject javaField, jclass annotationType) { + ScopedFastNativeObjectAccess soa(env); + StackHandleScope<1> hs(soa.Self()); + ArtField* field = soa.Decode<mirror::Field*>(javaField)->GetArtField(); + if (field->GetDeclaringClass()->IsProxyClass()) { + return nullptr; + } + Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType))); + return soa.AddLocalReference<jobject>(field->GetDexFile()->GetAnnotationForField(field, klass)); +} + +static jobjectArray Field_getDeclaredAnnotations(JNIEnv* env, jobject javaField) { + ScopedFastNativeObjectAccess soa(env); + ArtField* field = soa.Decode<mirror::Field*>(javaField)->GetArtField(); + if (field->GetDeclaringClass()->IsProxyClass()) { + // Return an empty array instead of a null pointer. + mirror::Class* annotation_array_class = + soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_annotation_Annotation__array); + mirror::ObjectArray<mirror::Object>* empty_array = + mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), annotation_array_class, 0); + return soa.AddLocalReference<jobjectArray>(empty_array); + } + return soa.AddLocalReference<jobjectArray>(field->GetDexFile()->GetAnnotationsForField(field)); +} + +static jobjectArray Field_getSignatureAnnotation(JNIEnv* env, jobject javaField) { + ScopedFastNativeObjectAccess soa(env); + ArtField* field = soa.Decode<mirror::Field*>(javaField)->GetArtField(); + if (field->GetDeclaringClass()->IsProxyClass()) { + return nullptr; + } + return soa.AddLocalReference<jobjectArray>( + field->GetDexFile()->GetSignatureAnnotationForField(field)); +} + +static jboolean Field_isAnnotationPresentNative(JNIEnv* env, jobject javaField, + jclass annotationType) { + ScopedFastNativeObjectAccess soa(env); + StackHandleScope<1> hs(soa.Self()); + ArtField* field = soa.Decode<mirror::Field*>(javaField)->GetArtField(); + if (field->GetDeclaringClass()->IsProxyClass()) { + return false; + } + Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType))); + return field->GetDexFile()->IsFieldAnnotationPresent(field, klass); +} + static JNINativeMethod gMethods[] = { NATIVE_METHOD(Field, get, "!(Ljava/lang/Object;)Ljava/lang/Object;"), NATIVE_METHOD(Field, getBoolean, "!(Ljava/lang/Object;)Z"), NATIVE_METHOD(Field, getByte, "!(Ljava/lang/Object;)B"), NATIVE_METHOD(Field, getChar, "!(Ljava/lang/Object;)C"), + NATIVE_METHOD(Field, getAnnotationNative, + "!(Ljava/lang/Class;)Ljava/lang/annotation/Annotation;"), + NATIVE_METHOD(Field, getDeclaredAnnotations, "!()[Ljava/lang/annotation/Annotation;"), + NATIVE_METHOD(Field, getSignatureAnnotation, "!()[Ljava/lang/String;"), NATIVE_METHOD(Field, getDouble, "!(Ljava/lang/Object;)D"), NATIVE_METHOD(Field, getFloat, "!(Ljava/lang/Object;)F"), NATIVE_METHOD(Field, getInt, "!(Ljava/lang/Object;)I"), NATIVE_METHOD(Field, getLong, "!(Ljava/lang/Object;)J"), NATIVE_METHOD(Field, getShort, "!(Ljava/lang/Object;)S"), + NATIVE_METHOD(Field, isAnnotationPresentNative, "!(Ljava/lang/Class;)Z"), NATIVE_METHOD(Field, set, "!(Ljava/lang/Object;Ljava/lang/Object;)V"), NATIVE_METHOD(Field, setBoolean, "!(Ljava/lang/Object;Z)V"), NATIVE_METHOD(Field, setByte, "!(Ljava/lang/Object;B)V"), diff --git a/runtime/native/java_lang_reflect_Method.cc b/runtime/native/java_lang_reflect_Method.cc index 9533b4dc8a..1219f85710 100644 --- a/runtime/native/java_lang_reflect_Method.cc +++ b/runtime/native/java_lang_reflect_Method.cc @@ -18,6 +18,7 @@ #include "art_method-inl.h" #include "class_linker.h" +#include "class_linker-inl.h" #include "jni_internal.h" #include "mirror/class-inl.h" #include "mirror/object-inl.h" @@ -28,35 +29,111 @@ namespace art { +static jobject Method_getAnnotationNative(JNIEnv* env, jobject javaMethod, jclass annotationType) { + ScopedFastNativeObjectAccess soa(env); + ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod); + if (method->GetDeclaringClass()->IsProxyClass()) { + return nullptr; + } + StackHandleScope<1> hs(soa.Self()); + Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType))); + return soa.AddLocalReference<jobject>( + method->GetDexFile()->GetAnnotationForMethod(method, klass)); +} + +static jobjectArray Method_getDeclaredAnnotations(JNIEnv* env, jobject javaMethod) { + ScopedFastNativeObjectAccess soa(env); + ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod); + if (method->GetDeclaringClass()->IsProxyClass()) { + // Return an empty array instead of a null pointer. + mirror::Class* annotation_array_class = + soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_annotation_Annotation__array); + mirror::ObjectArray<mirror::Object>* empty_array = + mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), annotation_array_class, 0); + return soa.AddLocalReference<jobjectArray>(empty_array); + } + return soa.AddLocalReference<jobjectArray>(method->GetDexFile()->GetAnnotationsForMethod(method)); +} + +static jobject Method_getDefaultValue(JNIEnv* env, jobject javaMethod) { + ScopedFastNativeObjectAccess soa(env); + ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod); + if (!method->GetDeclaringClass()->IsAnnotation()) { + return nullptr; + } + return soa.AddLocalReference<jobject>(method->GetDexFile()->GetAnnotationDefaultValue(method)); +} + +static jobjectArray Method_getExceptionTypes(JNIEnv* env, jobject javaMethod) { + ScopedFastNativeObjectAccess soa(env); + ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod); + if (method->GetDeclaringClass()->IsProxyClass()) { + mirror::Class* klass = method->GetDeclaringClass(); + int throws_index = -1; + size_t i = 0; + for (const auto& m : klass->GetVirtualMethods(sizeof(void*))) { + if (&m == method) { + throws_index = i; + break; + } + ++i; + } + CHECK_NE(throws_index, -1); + mirror::ObjectArray<mirror::Class>* declared_exceptions = klass->GetThrows()->Get(throws_index); + return soa.AddLocalReference<jobjectArray>(declared_exceptions->Clone(soa.Self())); + } else { + mirror::ObjectArray<mirror::Object>* result_array = + method->GetDexFile()->GetExceptionTypesForMethod(method); + if (result_array == nullptr) { + // Return an empty array instead of a null pointer + mirror::Class* class_class = mirror::Class::GetJavaLangClass(); + mirror::Class* class_array_class = + Runtime::Current()->GetClassLinker()->FindArrayClass(soa.Self(), &class_class); + mirror::ObjectArray<mirror::Object>* empty_array = + mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), class_array_class, 0); + return soa.AddLocalReference<jobjectArray>(empty_array); + } else { + return soa.AddLocalReference<jobjectArray>(result_array); + } + } +} + +static jobjectArray Method_getParameterAnnotationsNative(JNIEnv* env, jobject javaMethod) { + ScopedFastNativeObjectAccess soa(env); + ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod); + if (method->GetDeclaringClass()->IsProxyClass()) { + return nullptr; + } + return soa.AddLocalReference<jobjectArray>(method->GetDexFile()->GetParameterAnnotations(method)); +} + static jobject Method_invoke(JNIEnv* env, jobject javaMethod, jobject javaReceiver, jobject javaArgs) { ScopedFastNativeObjectAccess soa(env); return InvokeMethod(soa, javaMethod, javaReceiver, javaArgs); } -static jobject Method_getExceptionTypesNative(JNIEnv* env, jobject javaMethod) { +static jboolean Method_isAnnotationPresentNative(JNIEnv* env, jobject javaMethod, + jclass annotationType) { ScopedFastNativeObjectAccess soa(env); - ArtMethod* proxy_method = ArtMethod::FromReflectedMethod(soa, javaMethod); - CHECK(proxy_method->GetDeclaringClass()->IsProxyClass()); - mirror::Class* proxy_class = proxy_method->GetDeclaringClass(); - int throws_index = -1; - size_t i = 0; - for (const auto& m : proxy_class->GetVirtualMethods(sizeof(void*))) { - if (&m == proxy_method) { - throws_index = i; - break; - } - ++i; + ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod); + if (method->GetDeclaringClass()->IsProxyClass()) { + return false; } - CHECK_NE(throws_index, -1); - mirror::ObjectArray<mirror::Class>* declared_exceptions = - proxy_class->GetThrows()->Get(throws_index); - return soa.AddLocalReference<jobject>(declared_exceptions->Clone(soa.Self())); + StackHandleScope<1> hs(soa.Self()); + Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType))); + return method->GetDexFile()->IsMethodAnnotationPresent(method, klass); } static JNINativeMethod gMethods[] = { + NATIVE_METHOD(Method, getAnnotationNative, + "!(Ljava/lang/Class;)Ljava/lang/annotation/Annotation;"), + NATIVE_METHOD(Method, getDeclaredAnnotations, "!()[Ljava/lang/annotation/Annotation;"), + NATIVE_METHOD(Method, getDefaultValue, "!()Ljava/lang/Object;"), + NATIVE_METHOD(Method, getExceptionTypes, "!()[Ljava/lang/Class;"), + NATIVE_METHOD(Method, getParameterAnnotationsNative, "!()[[Ljava/lang/annotation/Annotation;"), NATIVE_METHOD(Method, invoke, "!(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"), - NATIVE_METHOD(Method, getExceptionTypesNative, "!()[Ljava/lang/Class;"), + NATIVE_METHOD(Method, isAnnotationPresentNative, "!(Ljava/lang/Class;)Z"), }; void register_java_lang_reflect_Method(JNIEnv* env) { diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc index 0c7cce908c..e2c3afbcbc 100644 --- a/runtime/well_known_classes.cc +++ b/runtime/well_known_classes.cc @@ -35,6 +35,7 @@ jclass WellKnownClasses::dalvik_system_DexPathList; jclass WellKnownClasses::dalvik_system_DexPathList__Element; jclass WellKnownClasses::dalvik_system_PathClassLoader; jclass WellKnownClasses::dalvik_system_VMRuntime; +jclass WellKnownClasses::java_lang_annotation_Annotation__array; jclass WellKnownClasses::java_lang_BootClassLoader; jclass WellKnownClasses::java_lang_ClassLoader; jclass WellKnownClasses::java_lang_ClassNotFoundException; @@ -59,6 +60,8 @@ jclass WellKnownClasses::java_lang_Throwable; jclass WellKnownClasses::java_nio_DirectByteBuffer; jclass WellKnownClasses::java_util_ArrayList; jclass WellKnownClasses::java_util_Collections; +jclass WellKnownClasses::libcore_reflect_AnnotationFactory; +jclass WellKnownClasses::libcore_reflect_AnnotationMember; jclass WellKnownClasses::libcore_util_EmptyArray; jclass WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk; jclass WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer; @@ -120,6 +123,8 @@ jmethodID WellKnownClasses::java_lang_Thread_run; jmethodID WellKnownClasses::java_lang_Thread__UncaughtExceptionHandler_uncaughtException; jmethodID WellKnownClasses::java_lang_ThreadGroup_removeThread; jmethodID WellKnownClasses::java_nio_DirectByteBuffer_init; +jmethodID WellKnownClasses::libcore_reflect_AnnotationFactory_createAnnotation; +jmethodID WellKnownClasses::libcore_reflect_AnnotationMember_init; jmethodID WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer_broadcast; jmethodID WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer_dispatch; @@ -213,6 +218,7 @@ void WellKnownClasses::Init(JNIEnv* env) { dalvik_system_PathClassLoader = CacheClass(env, "dalvik/system/PathClassLoader"); dalvik_system_VMRuntime = CacheClass(env, "dalvik/system/VMRuntime"); + java_lang_annotation_Annotation__array = CacheClass(env, "[Ljava/lang/annotation/Annotation;"); java_lang_BootClassLoader = CacheClass(env, "java/lang/BootClassLoader"); java_lang_ClassLoader = CacheClass(env, "java/lang/ClassLoader"); java_lang_ClassNotFoundException = CacheClass(env, "java/lang/ClassNotFoundException"); @@ -238,6 +244,8 @@ void WellKnownClasses::Init(JNIEnv* env) { java_nio_DirectByteBuffer = CacheClass(env, "java/nio/DirectByteBuffer"); java_util_ArrayList = CacheClass(env, "java/util/ArrayList"); java_util_Collections = CacheClass(env, "java/util/Collections"); + libcore_reflect_AnnotationFactory = CacheClass(env, "libcore/reflect/AnnotationFactory"); + libcore_reflect_AnnotationMember = CacheClass(env, "libcore/reflect/AnnotationMember"); libcore_util_EmptyArray = CacheClass(env, "libcore/util/EmptyArray"); org_apache_harmony_dalvik_ddmc_Chunk = CacheClass(env, "org/apache/harmony/dalvik/ddmc/Chunk"); org_apache_harmony_dalvik_ddmc_DdmServer = CacheClass(env, "org/apache/harmony/dalvik/ddmc/DdmServer"); @@ -262,6 +270,8 @@ void WellKnownClasses::Init(JNIEnv* env) { java_lang_Thread__UncaughtExceptionHandler_uncaughtException = CacheMethod(env, java_lang_Thread__UncaughtExceptionHandler, false, "uncaughtException", "(Ljava/lang/Thread;Ljava/lang/Throwable;)V"); java_lang_ThreadGroup_removeThread = CacheMethod(env, java_lang_ThreadGroup, false, "removeThread", "(Ljava/lang/Thread;)V"); java_nio_DirectByteBuffer_init = CacheMethod(env, java_nio_DirectByteBuffer, false, "<init>", "(JI)V"); + libcore_reflect_AnnotationFactory_createAnnotation = CacheMethod(env, libcore_reflect_AnnotationFactory, true, "createAnnotation", "(Ljava/lang/Class;[Llibcore/reflect/AnnotationMember;)Ljava/lang/annotation/Annotation;"); + libcore_reflect_AnnotationMember_init = CacheMethod(env, libcore_reflect_AnnotationMember, false, "<init>", "(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/reflect/Method;)V"); org_apache_harmony_dalvik_ddmc_DdmServer_broadcast = CacheMethod(env, org_apache_harmony_dalvik_ddmc_DdmServer, true, "broadcast", "(I)V"); org_apache_harmony_dalvik_ddmc_DdmServer_dispatch = CacheMethod(env, org_apache_harmony_dalvik_ddmc_DdmServer, true, "dispatch", "(I[BII)Lorg/apache/harmony/dalvik/ddmc/Chunk;"); diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h index 6dd8168cbf..c8562917e9 100644 --- a/runtime/well_known_classes.h +++ b/runtime/well_known_classes.h @@ -46,6 +46,7 @@ struct WellKnownClasses { static jclass dalvik_system_DexPathList__Element; static jclass dalvik_system_PathClassLoader; static jclass dalvik_system_VMRuntime; + static jclass java_lang_annotation_Annotation__array; static jclass java_lang_BootClassLoader; static jclass java_lang_ClassLoader; static jclass java_lang_ClassNotFoundException; @@ -70,6 +71,8 @@ struct WellKnownClasses { static jclass java_util_ArrayList; static jclass java_util_Collections; static jclass java_nio_DirectByteBuffer; + static jclass libcore_reflect_AnnotationFactory; + static jclass libcore_reflect_AnnotationMember; static jclass libcore_util_EmptyArray; static jclass org_apache_harmony_dalvik_ddmc_Chunk; static jclass org_apache_harmony_dalvik_ddmc_DdmServer; @@ -131,6 +134,8 @@ struct WellKnownClasses { static jmethodID java_lang_Thread__UncaughtExceptionHandler_uncaughtException; static jmethodID java_lang_ThreadGroup_removeThread; static jmethodID java_nio_DirectByteBuffer_init; + static jmethodID libcore_reflect_AnnotationFactory_createAnnotation; + static jmethodID libcore_reflect_AnnotationMember_init; static jmethodID org_apache_harmony_dalvik_ddmc_DdmServer_broadcast; static jmethodID org_apache_harmony_dalvik_ddmc_DdmServer_dispatch; |