Move annotations to native.

Art side of this change. There is also a corresponding Libcore change.

Seeing ~2-3x speedup over dalvik KK MR1 in AnnotatedElementBenchmark.
Benchmark			 Speedup of Art AOSP to Dalvik KK MR1
GetAllReturnsLargeAnnotation	 2.99
GetAllReturnsMarkerAnnotation	 2.20
GetAllReturnsNoAnnotation	 2.43
GetAllReturnsSmallAnnotation	 2.52
GetAllReturnsThreeAnnotations	 2.87
GetAnnotationsOnSubclass	 2.42
GetDeclaredAnnotationsOnSubclass 2.49
GetFieldAnnotation		 2.68
GetFieldAnnotations		 2.60
GetMethodAnnotation		 2.66
GetMethodAnnotations		 2.61
GetParameterAnnotations		 2.52
GetTypeAnnotation		 2.56
GetTypeAnnotations		 2.17
IsFieldAnnotationPresent	 3.26
IsMethodAnnotationPresent	 4.99
IsTypeAnnotationPresent		 1.34

Change-Id: Ibdbb6d23b17eaab6e83c8774b1bb9401e8227941
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index b547d07..dc273d8 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -5546,6 +5546,36 @@
   }
 }
 
+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 7243a25..fbf4035 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -229,6 +229,12 @@
       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 52590a59..213f25d 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 @@
   }
 }
 
+// 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 &parameter_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 @@
   }
 }
 
-// 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 fc805f8..8928321 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 @@
     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 @@
 
   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 228fd27..949ff5f 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -505,6 +505,16 @@
   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 cbcb517..ef257ae 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -831,6 +831,9 @@
                                        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 c337e91..b9cc219 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -426,6 +426,45 @@
   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 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 @@
   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 93ba84a..cf3346d 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 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 5bbb0dc..cc60fe0 100644
--- a/runtime/native/java_lang_reflect_Field.cc
+++ b/runtime/native/java_lang_reflect_Field.cc
@@ -415,16 +415,51 @@
   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();
+  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();
+  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();
+  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();
+  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 9533b4d..2f0e7fe 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 0c7cce9..e2c3afb 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -35,6 +35,7 @@
 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_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__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 @@
   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 @@
   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 @@
   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 6dd8168..c856291 100644
--- a/runtime/well_known_classes.h
+++ b/runtime/well_known_classes.h
@@ -46,6 +46,7 @@
   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 @@
   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 @@
   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;