diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index 52590a5..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,
