Add AbstractMethod, Constructor, Method

Moves functionality to ART from libcore. Precursor to moving
ArtMethods to native. Mostly performance improvements.

N5 perf before (irrelevant results removed):
            Class_getConstructor  962.87 ===========
         Class_getDeclaredMethod 2394.37 ============================
                 Class_getMethod 2509.20 ==============================
               Class_newInstance 1999.81 =======================
                  Method_invokeI 1439.02 =================
          Method_invokePreBoxedI 1415.82 ================
            Method_invokeStaticI 1456.24 =================
    Method_invokeStaticPreBoxedI 1427.32 =================
            Method_invokeStaticV  814.47 =========
                  Method_invokeV  816.56 =========
After:
                       benchmark      ns linear runtime
            Class_getConstructor 1302.04 ================
         Class_getDeclaredMethod 1459.01 ==================
                 Class_getMethod 1560.40 ===================
               Class_newInstance 2029.94 =========================
                  Method_invokeI 1312.89 ================
          Method_invokePreBoxedI 1255.01 ===============
            Method_invokeStaticI 1289.13 ===============
    Method_invokeStaticPreBoxedI 1196.52 ==============
            Method_invokeStaticV  790.82 =========
                  Method_invokeV  791.73 =========

Performance improvements are more than just fixing regressions introduced
in: http://android-review.googlesource.com/#/c/146069/

Bug: 19264997

Change-Id: Ife79c469fdb09f30e3aefcfc3e0ce5ed32303fce
diff --git a/dalvikvm/dalvikvm.cc b/dalvikvm/dalvikvm.cc
index 7839aa8..fd03002 100644
--- a/dalvikvm/dalvikvm.cc
+++ b/dalvikvm/dalvikvm.cc
@@ -50,6 +50,7 @@
   int modifiers = env->CallIntMethod(reflected.get(), mid);
   static const int PUBLIC = 0x0001;  // java.lang.reflect.Modifiers.PUBLIC
   if ((modifiers & PUBLIC) == 0) {
+    fprintf(stderr, "Modifiers mismatch\n");
     return false;
   }
   return true;
diff --git a/runtime/Android.mk b/runtime/Android.mk
index d3488fc..86201ba 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -100,11 +100,13 @@
   linear_alloc.cc \
   mem_map.cc \
   memory_region.cc \
+  mirror/abstract_method.cc \
   mirror/art_method.cc \
   mirror/array.cc \
   mirror/class.cc \
   mirror/dex_cache.cc \
   mirror/field.cc \
+  mirror/method.cc \
   mirror/object.cc \
   mirror/reference.cc \
   mirror/stack_trace_element.cc \
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 4e59217..85b245f 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -59,6 +59,7 @@
 #include "mirror/dex_cache-inl.h"
 #include "mirror/field.h"
 #include "mirror/iftable-inl.h"
+#include "mirror/method.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
 #include "mirror/proxy.h"
@@ -258,8 +259,8 @@
   CHECK(!init_done_);
 
   // java_lang_Class comes first, it's needed for AllocClass
-  Thread* self = Thread::Current();
-  gc::Heap* heap = Runtime::Current()->GetHeap();
+  Thread* const self = Thread::Current();
+  gc::Heap* const heap = Runtime::Current()->GetHeap();
   // The GC can't handle an object with a null class since we can't get the size of this object.
   heap->IncrementDisableMovingGC(self);
   StackHandleScope<64> hs(self);  // 64 is picked arbitrarily.
@@ -436,20 +437,19 @@
 
   // Object, String and DexCache need to be rerun through FindSystemClass to finish init
   mirror::Class::SetStatus(java_lang_Object, mirror::Class::kStatusNotReady, self);
-  mirror::Class* Object_class = FindSystemClass(self, "Ljava/lang/Object;");
-  CHECK_EQ(java_lang_Object.Get(), Object_class);
+  CHECK_EQ(java_lang_Object.Get(), FindSystemClass(self, "Ljava/lang/Object;"));
   CHECK_EQ(java_lang_Object->GetObjectSize(), mirror::Object::InstanceSize());
   mirror::Class::SetStatus(java_lang_String, mirror::Class::kStatusNotReady, self);
   mirror::Class* String_class = FindSystemClass(self, "Ljava/lang/String;");
-  std::ostringstream os1, os2;
-  java_lang_String->DumpClass(os1, mirror::Class::kDumpClassFullDetail);
-  String_class->DumpClass(os2, mirror::Class::kDumpClassFullDetail);
-  CHECK_EQ(java_lang_String.Get(), String_class) << os1.str() << "\n\n" << os2.str();
+  if (java_lang_String.Get() != String_class) {
+    std::ostringstream os1, os2;
+    java_lang_String->DumpClass(os1, mirror::Class::kDumpClassFullDetail);
+    String_class->DumpClass(os2, mirror::Class::kDumpClassFullDetail);
+    LOG(FATAL) << os1.str() << "\n\n" << os2.str();
+  }
   CHECK_EQ(java_lang_String->GetObjectSize(), mirror::String::InstanceSize());
   mirror::Class::SetStatus(java_lang_DexCache, mirror::Class::kStatusNotReady, self);
-  mirror::Class* DexCache_class = FindSystemClass(self, "Ljava/lang/DexCache;");
-  CHECK_EQ(java_lang_String.Get(), String_class);
-  CHECK_EQ(java_lang_DexCache.Get(), DexCache_class);
+  CHECK_EQ(java_lang_DexCache.Get(), FindSystemClass(self, "Ljava/lang/DexCache;"));
   CHECK_EQ(java_lang_DexCache->GetObjectSize(), mirror::DexCache::InstanceSize());
 
   // Setup the primitive array type classes - can't be done until Object has a vtable.
@@ -459,17 +459,14 @@
   SetClassRoot(kByteArrayClass, FindSystemClass(self, "[B"));
   mirror::ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass));
 
-  mirror::Class* found_char_array_class = FindSystemClass(self, "[C");
-  CHECK_EQ(char_array_class.Get(), found_char_array_class);
+  CHECK_EQ(char_array_class.Get(), FindSystemClass(self, "[C"));
 
   SetClassRoot(kShortArrayClass, FindSystemClass(self, "[S"));
   mirror::ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass));
 
-  mirror::Class* found_int_array_class = FindSystemClass(self, "[I");
-  CHECK_EQ(int_array_class.Get(), found_int_array_class);
+  CHECK_EQ(int_array_class.Get(), FindSystemClass(self, "[I"));
 
-  mirror::Class* found_long_array_class = FindSystemClass(self, "[J");
-  CHECK_EQ(long_array_class.Get(), found_long_array_class);
+  CHECK_EQ(long_array_class.Get(), FindSystemClass(self, "[J"));
 
   SetClassRoot(kFloatArrayClass, FindSystemClass(self, "[F"));
   mirror::FloatArray::SetArrayClass(GetClassRoot(kFloatArrayClass));
@@ -477,97 +474,101 @@
   SetClassRoot(kDoubleArrayClass, FindSystemClass(self, "[D"));
   mirror::DoubleArray::SetArrayClass(GetClassRoot(kDoubleArrayClass));
 
-  mirror::Class* found_class_array_class = FindSystemClass(self, "[Ljava/lang/Class;");
-  CHECK_EQ(class_array_class.Get(), found_class_array_class);
+  CHECK_EQ(class_array_class.Get(), FindSystemClass(self, "[Ljava/lang/Class;"));
 
-  mirror::Class* found_object_array_class = FindSystemClass(self, "[Ljava/lang/Object;");
-  CHECK_EQ(object_array_class.Get(), found_object_array_class);
+  CHECK_EQ(object_array_class.Get(), FindSystemClass(self, "[Ljava/lang/Object;"));
 
   // Setup the single, global copy of "iftable".
-  mirror::Class* java_lang_Cloneable = FindSystemClass(self, "Ljava/lang/Cloneable;");
-  CHECK(java_lang_Cloneable != nullptr);
-  mirror::Class* java_io_Serializable = FindSystemClass(self, "Ljava/io/Serializable;");
-  CHECK(java_io_Serializable != nullptr);
+  auto java_lang_Cloneable = hs.NewHandle(FindSystemClass(self, "Ljava/lang/Cloneable;"));
+  CHECK(java_lang_Cloneable.Get() != nullptr);
+  auto java_io_Serializable = hs.NewHandle(FindSystemClass(self, "Ljava/io/Serializable;"));
+  CHECK(java_io_Serializable.Get() != nullptr);
   // We assume that Cloneable/Serializable don't have superinterfaces -- normally we'd have to
   // crawl up and explicitly list all of the supers as well.
-  {
-    mirror::IfTable* array_iftable = array_iftable_.Read();
-    array_iftable->SetInterface(0, java_lang_Cloneable);
-    array_iftable->SetInterface(1, java_io_Serializable);
-  }
+  array_iftable_.Read()->SetInterface(0, java_lang_Cloneable.Get());
+  array_iftable_.Read()->SetInterface(1, java_io_Serializable.Get());
 
-  // Sanity check Class[] and Object[]'s interfaces.
-  CHECK_EQ(java_lang_Cloneable, mirror::Class::GetDirectInterface(self, class_array_class, 0));
-  CHECK_EQ(java_io_Serializable, mirror::Class::GetDirectInterface(self, class_array_class, 1));
-  CHECK_EQ(java_lang_Cloneable, mirror::Class::GetDirectInterface(self, object_array_class, 0));
-  CHECK_EQ(java_io_Serializable, mirror::Class::GetDirectInterface(self, object_array_class, 1));
+  // Sanity check Class[] and Object[]'s interfaces. GetDirectInterface may cause thread
+  // suspension.
+  CHECK_EQ(java_lang_Cloneable.Get(),
+           mirror::Class::GetDirectInterface(self, class_array_class, 0));
+  CHECK_EQ(java_io_Serializable.Get(),
+           mirror::Class::GetDirectInterface(self, class_array_class, 1));
+  CHECK_EQ(java_lang_Cloneable.Get(),
+           mirror::Class::GetDirectInterface(self, object_array_class, 0));
+  CHECK_EQ(java_io_Serializable.Get(),
+           mirror::Class::GetDirectInterface(self, object_array_class, 1));
   // Run Class, ArtField, and ArtMethod through FindSystemClass. This initializes their
   // dex_cache_ fields and register them in class_table_.
-  mirror::Class* Class_class = FindSystemClass(self, "Ljava/lang/Class;");
-  CHECK_EQ(java_lang_Class.Get(), Class_class);
+  CHECK_EQ(java_lang_Class.Get(), FindSystemClass(self, "Ljava/lang/Class;"));
 
   mirror::Class::SetStatus(java_lang_reflect_ArtMethod, mirror::Class::kStatusNotReady, self);
-  mirror::Class* Art_method_class = FindSystemClass(self, "Ljava/lang/reflect/ArtMethod;");
-  CHECK_EQ(java_lang_reflect_ArtMethod.Get(), Art_method_class);
-
-  mirror::Class* String_array_class =
-      FindSystemClass(self, GetClassRootDescriptor(kJavaLangStringArrayClass));
-  CHECK_EQ(object_array_string.Get(), String_array_class);
-
-  mirror::Class* Art_method_array_class =
-      FindSystemClass(self, GetClassRootDescriptor(kJavaLangReflectArtMethodArrayClass));
-  CHECK_EQ(object_array_art_method.Get(), Art_method_array_class);
+  CHECK_EQ(java_lang_reflect_ArtMethod.Get(),
+           FindSystemClass(self, "Ljava/lang/reflect/ArtMethod;"));
+  CHECK_EQ(object_array_string.Get(),
+           FindSystemClass(self, GetClassRootDescriptor(kJavaLangStringArrayClass)));
+  CHECK_EQ(object_array_art_method.Get(),
+           FindSystemClass(self, GetClassRootDescriptor(kJavaLangReflectArtMethodArrayClass)));
 
   // End of special init trickery, subsequent classes may be loaded via FindSystemClass.
 
   // Create java.lang.reflect.Proxy root.
-  mirror::Class* java_lang_reflect_Proxy = FindSystemClass(self, "Ljava/lang/reflect/Proxy;");
-  SetClassRoot(kJavaLangReflectProxy, java_lang_reflect_Proxy);
+  SetClassRoot(kJavaLangReflectProxy, FindSystemClass(self, "Ljava/lang/reflect/Proxy;"));
 
   // Create java.lang.reflect.Field.class root.
-  mirror::Class* java_lang_reflect_Field = FindSystemClass(self, "Ljava/lang/reflect/Field;");
-  CHECK(java_lang_reflect_Field != nullptr);
-  SetClassRoot(kJavaLangReflectField, java_lang_reflect_Field);
-  mirror::Field::SetClass(java_lang_reflect_Field);
+  auto* class_root = FindSystemClass(self, "Ljava/lang/reflect/Field;");
+  CHECK(class_root != nullptr);
+  SetClassRoot(kJavaLangReflectField, class_root);
+  mirror::Field::SetClass(class_root);
 
   // Create java.lang.reflect.Field array root.
-  mirror::Class* java_lang_reflect_Field_array =
-      FindSystemClass(self, "[Ljava/lang/reflect/Field;");
-  CHECK(java_lang_reflect_Field_array != nullptr);
-  SetClassRoot(kJavaLangReflectFieldArrayClass, java_lang_reflect_Field_array);
-  mirror::Field::SetArrayClass(java_lang_reflect_Field_array);
+  class_root = FindSystemClass(self, "[Ljava/lang/reflect/Field;");
+  CHECK(class_root != nullptr);
+  SetClassRoot(kJavaLangReflectFieldArrayClass, class_root);
+  mirror::Field::SetArrayClass(class_root);
+
+  // Create java.lang.reflect.Constructor.class root and array root.
+  class_root = FindSystemClass(self, "Ljava/lang/reflect/Constructor;");
+  CHECK(class_root != nullptr);
+  SetClassRoot(kJavaLangReflectConstructor, class_root);
+  mirror::Constructor::SetClass(class_root);
+  class_root = FindSystemClass(self, "[Ljava/lang/reflect/Constructor;");
+  CHECK(class_root != nullptr);
+  SetClassRoot(kJavaLangReflectConstructorArrayClass, class_root);
+  mirror::Constructor::SetArrayClass(class_root);
+
+  // Create java.lang.reflect.Method.class root and array root.
+  class_root = FindSystemClass(self, "Ljava/lang/reflect/Method;");
+  CHECK(class_root != nullptr);
+  SetClassRoot(kJavaLangReflectMethod, class_root);
+  mirror::Method::SetClass(class_root);
+  class_root = FindSystemClass(self, "[Ljava/lang/reflect/Method;");
+  CHECK(class_root != nullptr);
+  SetClassRoot(kJavaLangReflectMethodArrayClass, class_root);
+  mirror::Method::SetArrayClass(class_root);
 
   // java.lang.ref classes need to be specially flagged, but otherwise are normal classes
   // finish initializing Reference class
   mirror::Class::SetStatus(java_lang_ref_Reference, mirror::Class::kStatusNotReady, self);
-  mirror::Class* Reference_class = FindSystemClass(self, "Ljava/lang/ref/Reference;");
-  CHECK_EQ(java_lang_ref_Reference.Get(), Reference_class);
+  CHECK_EQ(java_lang_ref_Reference.Get(), FindSystemClass(self, "Ljava/lang/ref/Reference;"));
   CHECK_EQ(java_lang_ref_Reference->GetObjectSize(), mirror::Reference::InstanceSize());
   CHECK_EQ(java_lang_ref_Reference->GetClassSize(), mirror::Reference::ClassSize());
-  mirror::Class* java_lang_ref_FinalizerReference =
-      FindSystemClass(self, "Ljava/lang/ref/FinalizerReference;");
-  java_lang_ref_FinalizerReference->SetAccessFlags(
-      java_lang_ref_FinalizerReference->GetAccessFlags() |
-          kAccClassIsReference | kAccClassIsFinalizerReference);
-  mirror::Class* java_lang_ref_PhantomReference =
-      FindSystemClass(self, "Ljava/lang/ref/PhantomReference;");
-  java_lang_ref_PhantomReference->SetAccessFlags(
-      java_lang_ref_PhantomReference->GetAccessFlags() |
-          kAccClassIsReference | kAccClassIsPhantomReference);
-  mirror::Class* java_lang_ref_SoftReference =
-      FindSystemClass(self, "Ljava/lang/ref/SoftReference;");
-  java_lang_ref_SoftReference->SetAccessFlags(
-      java_lang_ref_SoftReference->GetAccessFlags() | kAccClassIsReference);
-  mirror::Class* java_lang_ref_WeakReference =
-      FindSystemClass(self, "Ljava/lang/ref/WeakReference;");
-  java_lang_ref_WeakReference->SetAccessFlags(
-      java_lang_ref_WeakReference->GetAccessFlags() |
-          kAccClassIsReference | kAccClassIsWeakReference);
+  class_root = FindSystemClass(self, "Ljava/lang/ref/FinalizerReference;");
+  class_root->SetAccessFlags(class_root->GetAccessFlags() |
+                             kAccClassIsReference | kAccClassIsFinalizerReference);
+  class_root = FindSystemClass(self, "Ljava/lang/ref/PhantomReference;");
+  class_root->SetAccessFlags(class_root->GetAccessFlags() | kAccClassIsReference |
+                             kAccClassIsPhantomReference);
+  class_root = FindSystemClass(self, "Ljava/lang/ref/SoftReference;");
+  class_root->SetAccessFlags(class_root->GetAccessFlags() | kAccClassIsReference);
+  class_root = FindSystemClass(self, "Ljava/lang/ref/WeakReference;");
+  class_root->SetAccessFlags(class_root->GetAccessFlags() | kAccClassIsReference |
+                             kAccClassIsWeakReference);
 
   // Setup the ClassLoader, verifying the object_size_.
-  mirror::Class* java_lang_ClassLoader = FindSystemClass(self, "Ljava/lang/ClassLoader;");
-  CHECK_EQ(java_lang_ClassLoader->GetObjectSize(), mirror::ClassLoader::InstanceSize());
-  SetClassRoot(kJavaLangClassLoader, java_lang_ClassLoader);
+  class_root = FindSystemClass(self, "Ljava/lang/ClassLoader;");
+  CHECK_EQ(class_root->GetObjectSize(), mirror::ClassLoader::InstanceSize());
+  SetClassRoot(kJavaLangClassLoader, class_root);
 
   // Set up java.lang.Throwable, java.lang.ClassNotFoundException, and
   // java.lang.StackTraceElement as a convenience.
@@ -911,6 +912,10 @@
   // String class root was set above
   mirror::Field::SetClass(GetClassRoot(kJavaLangReflectField));
   mirror::Field::SetArrayClass(GetClassRoot(kJavaLangReflectFieldArrayClass));
+  mirror::Constructor::SetClass(GetClassRoot(kJavaLangReflectConstructor));
+  mirror::Constructor::SetArrayClass(GetClassRoot(kJavaLangReflectConstructorArrayClass));
+  mirror::Method::SetClass(GetClassRoot(kJavaLangReflectMethod));
+  mirror::Method::SetArrayClass(GetClassRoot(kJavaLangReflectMethodArrayClass));
   mirror::Reference::SetClass(GetClassRoot(kJavaLangRefReference));
   mirror::BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass));
   mirror::ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass));
@@ -1096,22 +1101,26 @@
 }
 
 ClassLinker::~ClassLinker() {
-  mirror::Class::ResetClass();
-  mirror::String::ResetClass();
-  mirror::Reference::ResetClass();
   mirror::ArtMethod::ResetClass();
+  mirror::Class::ResetClass();
+  mirror::Constructor::ResetClass();
   mirror::Field::ResetClass();
-  mirror::Field::ResetArrayClass();
+  mirror::Method::ResetClass();
+  mirror::Reference::ResetClass();
+  mirror::StackTraceElement::ResetClass();
+  mirror::String::ResetClass();
+  mirror::Throwable::ResetClass();
   mirror::BooleanArray::ResetArrayClass();
   mirror::ByteArray::ResetArrayClass();
   mirror::CharArray::ResetArrayClass();
+  mirror::Constructor::ResetArrayClass();
   mirror::DoubleArray::ResetArrayClass();
+  mirror::Field::ResetArrayClass();
   mirror::FloatArray::ResetArrayClass();
+  mirror::Method::ResetArrayClass();
   mirror::IntArray::ResetArrayClass();
   mirror::LongArray::ResetArrayClass();
   mirror::ShortArray::ResetArrayClass();
-  mirror::Throwable::ResetClass();
-  mirror::StackTraceElement::ResetClass();
   STLDeleteElements(&oat_files_);
 }
 
@@ -2947,7 +2956,7 @@
                                              jobjectArray interfaces, jobject loader,
                                              jobjectArray methods, jobjectArray throws) {
   Thread* self = soa.Self();
-  StackHandleScope<8> hs(self);
+  StackHandleScope<9> hs(self);
   MutableHandle<mirror::Class> klass(hs.NewHandle(
       AllocClass(self, GetClassRoot(kJavaLangClass), sizeof(mirror::Class))));
   if (klass.Get() == nullptr) {
@@ -3001,8 +3010,10 @@
   }
 
   // Create virtual method using specified prototypes.
-  size_t num_virtual_methods =
-      soa.Decode<mirror::ObjectArray<mirror::ArtMethod>*>(methods)->GetLength();
+  auto h_methods = hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Method>*>(methods));
+  DCHECK_EQ(h_methods->GetClass(), mirror::Method::ArrayClass())
+    << PrettyClass(h_methods->GetClass());
+  const size_t num_virtual_methods = h_methods->GetLength();
   {
     mirror::ObjectArray<mirror::ArtMethod>* virtuals = AllocArtMethodArray(self,
                                                                            num_virtual_methods);
@@ -3014,9 +3025,7 @@
   }
   for (size_t i = 0; i < num_virtual_methods; ++i) {
     StackHandleScope<1> hs2(self);
-    mirror::ObjectArray<mirror::ArtMethod>* decoded_methods =
-        soa.Decode<mirror::ObjectArray<mirror::ArtMethod>*>(methods);
-    Handle<mirror::ArtMethod> prototype(hs2.NewHandle(decoded_methods->Get(i)));
+    Handle<mirror::ArtMethod> prototype(hs2.NewHandle(h_methods->Get(i)->GetArtMethod()));
     mirror::ArtMethod* clone = CreateProxyMethod(self, klass, prototype);
     if (UNLIKELY(clone == nullptr)) {
       CHECK(self->IsExceptionPending());  // OOME.
@@ -3066,9 +3075,7 @@
     CheckProxyConstructor(klass->GetDirectMethod(0));
     for (size_t i = 0; i < num_virtual_methods; ++i) {
       StackHandleScope<2> hs2(self);
-      mirror::ObjectArray<mirror::ArtMethod>* decoded_methods =
-          soa.Decode<mirror::ObjectArray<mirror::ArtMethod>*>(methods);
-      Handle<mirror::ArtMethod> prototype(hs2.NewHandle(decoded_methods->Get(i)));
+      Handle<mirror::ArtMethod> prototype(hs2.NewHandle(h_methods->Get(i)->GetArtMethod()));
       Handle<mirror::ArtMethod> virtual_method(hs2.NewHandle(klass->GetVirtualMethod(i)));
       CheckProxyMethod(virtual_method, prototype);
     }
@@ -3104,23 +3111,22 @@
                                                    mirror::ArtMethod* proxy_method) {
   DCHECK(proxy_class->IsProxyClass());
   DCHECK(proxy_method->IsProxyMethod());
-  // Locate the dex cache of the original interface/Object
-  mirror::DexCache* dex_cache = nullptr;
   {
     ReaderMutexLock mu(Thread::Current(), dex_lock_);
-    for (size_t i = 0; i != dex_caches_.size(); ++i) {
-      mirror::DexCache* a_dex_cache = GetDexCache(i);
-      if (proxy_method->HasSameDexCacheResolvedTypes(a_dex_cache->GetResolvedTypes())) {
-        dex_cache = a_dex_cache;
-        break;
+    // Locate the dex cache of the original interface/Object
+    for (const GcRoot<mirror::DexCache>& root : dex_caches_) {
+      auto* dex_cache = root.Read();
+      if (proxy_method->HasSameDexCacheResolvedTypes(dex_cache->GetResolvedTypes())) {
+        mirror::ArtMethod* resolved_method = dex_cache->GetResolvedMethod(
+            proxy_method->GetDexMethodIndex());
+        CHECK(resolved_method != nullptr);
+        return resolved_method;
       }
     }
   }
-  CHECK(dex_cache != nullptr);
-  uint32_t method_idx = proxy_method->GetDexMethodIndex();
-  mirror::ArtMethod* resolved_method = dex_cache->GetResolvedMethod(method_idx);
-  CHECK(resolved_method != nullptr);
-  return resolved_method;
+  LOG(FATAL) << "Didn't find dex cache for " << PrettyClass(proxy_class) << " "
+      << PrettyMethod(proxy_method);
+  UNREACHABLE();
 }
 
 
@@ -3163,8 +3169,11 @@
                                                   Handle<mirror::ArtMethod> prototype) {
   // Ensure prototype is in dex cache so that we can use the dex cache to look up the overridden
   // prototype method
-  prototype->GetDeclaringClass()->GetDexCache()->SetResolvedMethod(prototype->GetDexMethodIndex(),
-                                                                   prototype.Get());
+  auto* dex_cache = prototype->GetDeclaringClass()->GetDexCache();
+  // Avoid dirtying the dex cache unless we need to.
+  if (dex_cache->GetResolvedMethod(prototype->GetDexMethodIndex()) != prototype.Get()) {
+    dex_cache->SetResolvedMethod(prototype->GetDexMethodIndex(), prototype.Get());
+  }
   // We steal everything from the prototype (such as DexCache, invoke stub, etc.) then specialize
   // as necessary
   mirror::ArtMethod* method = down_cast<mirror::ArtMethod*>(prototype->Clone(self));
@@ -3198,6 +3207,7 @@
   // interface prototype. The exception to this are Constructors and the Class of the Proxy itself.
   CHECK(prototype->HasSameDexCacheResolvedMethods(method.Get()));
   CHECK(prototype->HasSameDexCacheResolvedTypes(method.Get()));
+  CHECK_EQ(prototype->GetDeclaringClass()->GetDexCache(), method->GetDexCache());
   CHECK_EQ(prototype->GetDexMethodIndex(), method->GetDexMethodIndex());
 
   CHECK_STREQ(method->GetName(), prototype->GetName());
@@ -5210,11 +5220,15 @@
     "Ljava/lang/DexCache;",
     "Ljava/lang/ref/Reference;",
     "Ljava/lang/reflect/ArtMethod;",
+    "Ljava/lang/reflect/Constructor;",
     "Ljava/lang/reflect/Field;",
+    "Ljava/lang/reflect/Method;",
     "Ljava/lang/reflect/Proxy;",
     "[Ljava/lang/String;",
     "[Ljava/lang/reflect/ArtMethod;",
+    "[Ljava/lang/reflect/Constructor;",
     "[Ljava/lang/reflect/Field;",
+    "[Ljava/lang/reflect/Method;",
     "Ljava/lang/ClassLoader;",
     "Ljava/lang/Throwable;",
     "Ljava/lang/ClassNotFoundException;",
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 68624b0..d7c625d 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -71,11 +71,15 @@
     kJavaLangDexCache,
     kJavaLangRefReference,
     kJavaLangReflectArtMethod,
+    kJavaLangReflectConstructor,
     kJavaLangReflectField,
+    kJavaLangReflectMethod,
     kJavaLangReflectProxy,
     kJavaLangStringArrayClass,
     kJavaLangReflectArtMethodArrayClass,
+    kJavaLangReflectConstructorArrayClass,
     kJavaLangReflectFieldArrayClass,
+    kJavaLangReflectMethodArrayClass,
     kJavaLangClassLoader,
     kJavaLangThrowable,
     kJavaLangClassNotFoundException,
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index a31a785..7bee98f 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -25,6 +25,7 @@
 #include "dex_file.h"
 #include "entrypoints/entrypoint_utils-inl.h"
 #include "gc/heap.h"
+#include "mirror/abstract_method.h"
 #include "mirror/accessible_object.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
@@ -463,6 +464,10 @@
     return !error;
   };
 
+  void addOffset(size_t offset, const char* name) {
+    offsets.push_back(CheckOffset(offset, name));
+  }
+
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(CheckOffsets);
 };
@@ -472,142 +477,162 @@
 
 struct ObjectOffsets : public CheckOffsets<mirror::Object> {
   ObjectOffsets() : CheckOffsets<mirror::Object>(false, "Ljava/lang/Object;") {
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Object, klass_),   "shadow$_klass_"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Object, monitor_), "shadow$_monitor_"));
+    addOffset(OFFSETOF_MEMBER(mirror::Object, klass_), "shadow$_klass_");
+    addOffset(OFFSETOF_MEMBER(mirror::Object, monitor_), "shadow$_monitor_");
 #ifdef USE_BAKER_OR_BROOKS_READ_BARRIER
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Object, x_rb_ptr_), "shadow$_x_rb_ptr_"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Object, x_xpadding_), "shadow$_x_xpadding_"));
+    addOffset(OFFSETOF_MEMBER(mirror::Object, x_rb_ptr_), "shadow$_x_rb_ptr_");
+    addOffset(OFFSETOF_MEMBER(mirror::Object, x_xpadding_), "shadow$_x_xpadding_");
 #endif
   };
 };
 
 struct ArtMethodOffsets : public CheckOffsets<mirror::ArtMethod> {
   ArtMethodOffsets() : CheckOffsets<mirror::ArtMethod>(false, "Ljava/lang/reflect/ArtMethod;") {
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, access_flags_),                   "accessFlags"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, declaring_class_),                      "declaringClass"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_cache_resolved_methods_),           "dexCacheResolvedMethods"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_cache_resolved_types_),             "dexCacheResolvedTypes"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_code_item_offset_),           "dexCodeItemOffset"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_method_index_),               "dexMethodIndex"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, method_index_),                   "methodIndex"));
+    addOffset(OFFSETOF_MEMBER(mirror::ArtMethod, access_flags_), "accessFlags");
+    addOffset(OFFSETOF_MEMBER(mirror::ArtMethod, declaring_class_), "declaringClass");
+    addOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_cache_resolved_methods_),
+              "dexCacheResolvedMethods");
+    addOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_cache_resolved_types_),
+              "dexCacheResolvedTypes");
+    addOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_code_item_offset_), "dexCodeItemOffset");
+    addOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_method_index_), "dexMethodIndex");
+    addOffset(OFFSETOF_MEMBER(mirror::ArtMethod, method_index_), "methodIndex");
   };
 };
 
 struct ClassOffsets : public CheckOffsets<mirror::Class> {
   ClassOffsets() : CheckOffsets<mirror::Class>(false, "Ljava/lang/Class;") {
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, access_flags_),                  "accessFlags"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, class_loader_),                  "classLoader"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, class_size_),                    "classSize"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, clinit_thread_id_),              "clinitThreadId"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, component_type_),                "componentType"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, dex_cache_),                     "dexCache"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, dex_cache_strings_),             "dexCacheStrings"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, dex_class_def_idx_),             "dexClassDefIndex"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, dex_type_idx_),                  "dexTypeIndex"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, direct_methods_),                "directMethods"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, ifields_),                       "iFields"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, iftable_),                       "ifTable"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, name_),                          "name"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, num_instance_fields_),           "numInstanceFields"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, num_reference_instance_fields_), "numReferenceInstanceFields"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, num_reference_static_fields_),   "numReferenceStaticFields"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, num_static_fields_),             "numStaticFields"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, object_size_),                   "objectSize"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, primitive_type_),                "primitiveType"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, reference_instance_offsets_),    "referenceInstanceOffsets"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, sfields_),                       "sFields"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, status_),                        "status"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, super_class_),                   "superClass"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, verify_error_class_),            "verifyErrorClass"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, virtual_methods_),               "virtualMethods"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, vtable_),                        "vtable"));
+    addOffset(OFFSETOF_MEMBER(mirror::Class, access_flags_), "accessFlags");
+    addOffset(OFFSETOF_MEMBER(mirror::Class, class_loader_), "classLoader");
+    addOffset(OFFSETOF_MEMBER(mirror::Class, class_size_), "classSize");
+    addOffset(OFFSETOF_MEMBER(mirror::Class, clinit_thread_id_), "clinitThreadId");
+    addOffset(OFFSETOF_MEMBER(mirror::Class, component_type_), "componentType");
+    addOffset(OFFSETOF_MEMBER(mirror::Class, dex_cache_), "dexCache");
+    addOffset(OFFSETOF_MEMBER(mirror::Class, dex_cache_strings_), "dexCacheStrings");
+    addOffset(OFFSETOF_MEMBER(mirror::Class, dex_class_def_idx_), "dexClassDefIndex");
+    addOffset(OFFSETOF_MEMBER(mirror::Class, dex_type_idx_), "dexTypeIndex");
+    addOffset(OFFSETOF_MEMBER(mirror::Class, direct_methods_), "directMethods");
+    addOffset(OFFSETOF_MEMBER(mirror::Class, ifields_), "iFields");
+    addOffset(OFFSETOF_MEMBER(mirror::Class, iftable_), "ifTable");
+    addOffset(OFFSETOF_MEMBER(mirror::Class, name_), "name");
+    addOffset(OFFSETOF_MEMBER(mirror::Class, num_instance_fields_), "numInstanceFields");
+    addOffset(OFFSETOF_MEMBER(mirror::Class, num_reference_instance_fields_),
+              "numReferenceInstanceFields");
+    addOffset(OFFSETOF_MEMBER(mirror::Class, num_reference_static_fields_),
+              "numReferenceStaticFields");
+    addOffset(OFFSETOF_MEMBER(mirror::Class, num_static_fields_), "numStaticFields");
+    addOffset(OFFSETOF_MEMBER(mirror::Class, object_size_), "objectSize");
+    addOffset(OFFSETOF_MEMBER(mirror::Class, primitive_type_), "primitiveType");
+    addOffset(OFFSETOF_MEMBER(mirror::Class, reference_instance_offsets_),
+              "referenceInstanceOffsets");
+    addOffset(OFFSETOF_MEMBER(mirror::Class, sfields_), "sFields");
+    addOffset(OFFSETOF_MEMBER(mirror::Class, status_), "status");
+    addOffset(OFFSETOF_MEMBER(mirror::Class, super_class_), "superClass");
+    addOffset(OFFSETOF_MEMBER(mirror::Class, verify_error_class_), "verifyErrorClass");
+    addOffset(OFFSETOF_MEMBER(mirror::Class, virtual_methods_), "virtualMethods");
+    addOffset(OFFSETOF_MEMBER(mirror::Class, vtable_), "vtable");
   };
 };
 
 struct StringOffsets : public CheckOffsets<mirror::String> {
   StringOffsets() : CheckOffsets<mirror::String>(false, "Ljava/lang/String;") {
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::String, count_),     "count"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::String, hash_code_), "hashCode"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::String, offset_),    "offset"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::String, array_),     "value"));
+    addOffset(OFFSETOF_MEMBER(mirror::String, count_), "count");
+    addOffset(OFFSETOF_MEMBER(mirror::String, hash_code_), "hashCode");
+    addOffset(OFFSETOF_MEMBER(mirror::String, offset_), "offset");
+    addOffset(OFFSETOF_MEMBER(mirror::String, array_), "value");
   };
 };
 
 struct ThrowableOffsets : public CheckOffsets<mirror::Throwable> {
   ThrowableOffsets() : CheckOffsets<mirror::Throwable>(false, "Ljava/lang/Throwable;") {
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Throwable, cause_),                 "cause"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Throwable, detail_message_),        "detailMessage"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Throwable, stack_state_),           "stackState"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Throwable, stack_trace_),           "stackTrace"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Throwable, suppressed_exceptions_), "suppressedExceptions"));
+    addOffset(OFFSETOF_MEMBER(mirror::Throwable, cause_), "cause");
+    addOffset(OFFSETOF_MEMBER(mirror::Throwable, detail_message_), "detailMessage");
+    addOffset(OFFSETOF_MEMBER(mirror::Throwable, stack_state_), "stackState");
+    addOffset(OFFSETOF_MEMBER(mirror::Throwable, stack_trace_), "stackTrace");
+    addOffset(OFFSETOF_MEMBER(mirror::Throwable, suppressed_exceptions_), "suppressedExceptions");
   };
 };
 
 struct StackTraceElementOffsets : public CheckOffsets<mirror::StackTraceElement> {
-  StackTraceElementOffsets() : CheckOffsets<mirror::StackTraceElement>(false, "Ljava/lang/StackTraceElement;") {
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::StackTraceElement, declaring_class_), "declaringClass"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::StackTraceElement, file_name_),       "fileName"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::StackTraceElement, line_number_),     "lineNumber"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::StackTraceElement, method_name_),     "methodName"));
+  StackTraceElementOffsets() : CheckOffsets<mirror::StackTraceElement>(
+      false, "Ljava/lang/StackTraceElement;") {
+    addOffset(OFFSETOF_MEMBER(mirror::StackTraceElement, declaring_class_), "declaringClass");
+    addOffset(OFFSETOF_MEMBER(mirror::StackTraceElement, file_name_), "fileName");
+    addOffset(OFFSETOF_MEMBER(mirror::StackTraceElement, line_number_), "lineNumber");
+    addOffset(OFFSETOF_MEMBER(mirror::StackTraceElement, method_name_), "methodName");
   };
 };
 
 struct ClassLoaderOffsets : public CheckOffsets<mirror::ClassLoader> {
   ClassLoaderOffsets() : CheckOffsets<mirror::ClassLoader>(false, "Ljava/lang/ClassLoader;") {
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ClassLoader, packages_),   "packages"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ClassLoader, parent_),     "parent"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ClassLoader, proxyCache_), "proxyCache"));
+    addOffset(OFFSETOF_MEMBER(mirror::ClassLoader, packages_), "packages");
+    addOffset(OFFSETOF_MEMBER(mirror::ClassLoader, parent_), "parent");
+    addOffset(OFFSETOF_MEMBER(mirror::ClassLoader, proxyCache_), "proxyCache");
   };
 };
 
 struct ProxyOffsets : public CheckOffsets<mirror::Proxy> {
   ProxyOffsets() : CheckOffsets<mirror::Proxy>(false, "Ljava/lang/reflect/Proxy;") {
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Proxy, h_), "h"));
+    addOffset(OFFSETOF_MEMBER(mirror::Proxy, h_), "h");
   };
 };
 
 struct DexCacheOffsets : public CheckOffsets<mirror::DexCache> {
   DexCacheOffsets() : CheckOffsets<mirror::DexCache>(false, "Ljava/lang/DexCache;") {
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::DexCache, dex_),                        "dex"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::DexCache, dex_file_),                   "dexFile"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::DexCache, location_),                   "location"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::DexCache, resolved_fields_),            "resolvedFields"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::DexCache, resolved_methods_),           "resolvedMethods"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::DexCache, resolved_types_),             "resolvedTypes"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::DexCache, strings_),                    "strings"));
+    addOffset(OFFSETOF_MEMBER(mirror::DexCache, dex_), "dex");
+    addOffset(OFFSETOF_MEMBER(mirror::DexCache, dex_file_), "dexFile");
+    addOffset(OFFSETOF_MEMBER(mirror::DexCache, location_), "location");
+    addOffset(OFFSETOF_MEMBER(mirror::DexCache, resolved_fields_), "resolvedFields");
+    addOffset(OFFSETOF_MEMBER(mirror::DexCache, resolved_methods_), "resolvedMethods");
+    addOffset(OFFSETOF_MEMBER(mirror::DexCache, resolved_types_), "resolvedTypes");
+    addOffset(OFFSETOF_MEMBER(mirror::DexCache, strings_), "strings");
   };
 };
 
 struct ReferenceOffsets : public CheckOffsets<mirror::Reference> {
   ReferenceOffsets() : CheckOffsets<mirror::Reference>(false, "Ljava/lang/ref/Reference;") {
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Reference, pending_next_),  "pendingNext"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Reference, queue_),         "queue"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Reference, queue_next_),    "queueNext"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Reference, referent_),      "referent"));
+    addOffset(OFFSETOF_MEMBER(mirror::Reference, pending_next_), "pendingNext");
+    addOffset(OFFSETOF_MEMBER(mirror::Reference, queue_), "queue");
+    addOffset(OFFSETOF_MEMBER(mirror::Reference, queue_next_), "queueNext");
+    addOffset(OFFSETOF_MEMBER(mirror::Reference, referent_), "referent");
   };
 };
 
 struct FinalizerReferenceOffsets : public CheckOffsets<mirror::FinalizerReference> {
-  FinalizerReferenceOffsets() : CheckOffsets<mirror::FinalizerReference>(false, "Ljava/lang/ref/FinalizerReference;") {
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::FinalizerReference, next_),   "next"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::FinalizerReference, prev_),   "prev"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::FinalizerReference, zombie_), "zombie"));
+  FinalizerReferenceOffsets() : CheckOffsets<mirror::FinalizerReference>(
+      false, "Ljava/lang/ref/FinalizerReference;") {
+    addOffset(OFFSETOF_MEMBER(mirror::FinalizerReference, next_), "next");
+    addOffset(OFFSETOF_MEMBER(mirror::FinalizerReference, prev_), "prev");
+    addOffset(OFFSETOF_MEMBER(mirror::FinalizerReference, zombie_), "zombie");
   };
 };
 
 struct AccessibleObjectOffsets : public CheckOffsets<mirror::AccessibleObject> {
-  AccessibleObjectOffsets() : CheckOffsets<mirror::AccessibleObject>(false, "Ljava/lang/reflect/AccessibleObject;") {
-    offsets.push_back(CheckOffset(mirror::AccessibleObject::FlagOffset().Uint32Value(),   "flag"));
+  AccessibleObjectOffsets() : CheckOffsets<mirror::AccessibleObject>(
+      false, "Ljava/lang/reflect/AccessibleObject;") {
+    addOffset(mirror::AccessibleObject::FlagOffset().Uint32Value(), "flag");
   };
 };
 
 struct FieldOffsets : public CheckOffsets<mirror::Field> {
   FieldOffsets() : CheckOffsets<mirror::Field>(false, "Ljava/lang/reflect/Field;") {
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Field, access_flags_),     "accessFlags"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Field, declaring_class_),  "declaringClass"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Field, dex_field_index_),  "dexFieldIndex"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Field, offset_),           "offset"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Field, type_),             "type"));
+    addOffset(OFFSETOF_MEMBER(mirror::Field, access_flags_), "accessFlags");
+    addOffset(OFFSETOF_MEMBER(mirror::Field, declaring_class_), "declaringClass");
+    addOffset(OFFSETOF_MEMBER(mirror::Field, dex_field_index_), "dexFieldIndex");
+    addOffset(OFFSETOF_MEMBER(mirror::Field, offset_), "offset");
+    addOffset(OFFSETOF_MEMBER(mirror::Field, type_), "type");
+  };
+};
+
+struct AbstractMethodOffsets : public CheckOffsets<mirror::AbstractMethod> {
+  AbstractMethodOffsets() : CheckOffsets<mirror::AbstractMethod>(
+      false, "Ljava/lang/reflect/AbstractMethod;") {
+    addOffset(OFFSETOF_MEMBER(mirror::AbstractMethod, access_flags_), "accessFlags");
+    addOffset(OFFSETOF_MEMBER(mirror::AbstractMethod, art_method_), "artMethod");
+    addOffset(OFFSETOF_MEMBER(mirror::AbstractMethod, declaring_class_), "declaringClass");
+    addOffset(OFFSETOF_MEMBER(mirror::AbstractMethod, declaring_class_of_overridden_method_),
+              "declaringClassOfOverriddenMethod");
+    addOffset(OFFSETOF_MEMBER(mirror::AbstractMethod, dex_method_index_), "dexMethodIndex");
   };
 };
 
@@ -629,6 +654,7 @@
   EXPECT_TRUE(FinalizerReferenceOffsets().Check());
   EXPECT_TRUE(AccessibleObjectOffsets().Check());
   EXPECT_TRUE(FieldOffsets().Check());
+  EXPECT_TRUE(AbstractMethodOffsets().Check());
 }
 
 TEST_F(ClassLinkerTest, FindClassNonexistent) {
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index 1d8df68..768f505 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -23,6 +23,7 @@
 #include "gc/accounting/card_table-inl.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
+#include "mirror/method.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
 #include "reflection.h"
@@ -257,7 +258,7 @@
     }
   }
 
-  // Call Proxy.invoke(Proxy proxy, ArtMethod method, Object[] args).
+  // Call Proxy.invoke(Proxy proxy, Method method, Object[] args).
   jvalue invocation_args[3];
   invocation_args[0].l = rcvr_jobj;
   invocation_args[1].l = interface_method_jobj;
@@ -274,10 +275,9 @@
       return zero;
     } else {
       StackHandleScope<1> hs(soa.Self());
-      Handle<mirror::ArtMethod> h_interface_method(
-          hs.NewHandle(soa.Decode<mirror::ArtMethod*>(interface_method_jobj)));
+      auto h_interface_method(hs.NewHandle(soa.Decode<mirror::Method*>(interface_method_jobj)));
       // This can cause thread suspension.
-      mirror::Class* result_type = h_interface_method->GetReturnType();
+      mirror::Class* result_type = h_interface_method->GetArtMethod()->GetReturnType();
       mirror::Object* result_ref = soa.Decode<mirror::Object*>(result);
       JValue result_unboxed;
       if (!UnboxPrimitiveForResult(result_ref, result_type, &result_unboxed)) {
@@ -293,10 +293,9 @@
     if (exception->IsCheckedException()) {
       mirror::Object* rcvr = soa.Decode<mirror::Object*>(rcvr_jobj);
       mirror::Class* proxy_class = rcvr->GetClass();
-      mirror::ArtMethod* interface_method =
-          soa.Decode<mirror::ArtMethod*>(interface_method_jobj);
+      mirror::Method* interface_method = soa.Decode<mirror::Method*>(interface_method_jobj);
       mirror::ArtMethod* proxy_method =
-          rcvr->GetClass()->FindVirtualMethodForInterface(interface_method);
+          rcvr->GetClass()->FindVirtualMethodForInterface(interface_method->GetArtMethod());
       int throws_index = -1;
       size_t num_virt_methods = proxy_class->NumVirtualMethods();
       for (size_t i = 0; i < num_virt_methods; i++) {
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 2e813c8..2e7e2df 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -26,6 +26,7 @@
 #include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/dex_cache-inl.h"
+#include "mirror/method.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
 #include "runtime.h"
@@ -760,11 +761,12 @@
   mirror::ArtMethod* interface_method = proxy_method->FindOverriddenMethod();
   DCHECK(interface_method != nullptr) << PrettyMethod(proxy_method);
   DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method);
-  jobject interface_method_jobj = soa.AddLocalReference<jobject>(interface_method);
+  self->EndAssertNoThreadSuspension(old_cause);
+  jobject interface_method_jobj = soa.AddLocalReference<jobject>(
+      mirror::Method::CreateFromArtMethod(soa.Self(), interface_method));
 
   // All naked Object*s should now be in jobjects, so its safe to go into the main invoke code
   // that performs allocations.
-  self->EndAssertNoThreadSuspension(old_cause);
   JValue result = InvokeProxyInvocationHandler(soa, shorty, rcvr_jobj, interface_method_jobj, args);
   // Restore references which might have moved.
   local_ref_visitor.FixupReferences();
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index 8a5461b..554a28d 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -42,6 +42,7 @@
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/field-inl.h"
+#include "mirror/method.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
 #include "mirror/string-inl.h"
@@ -361,19 +362,13 @@
     ScopedObjectAccess soa(env);
     mirror::ArtMethod* m = soa.DecodeMethod(mid);
     CHECK(!kMovingMethods);
-    ScopedLocalRef<jobject> art_method(env, soa.AddLocalReference<jobject>(m));
-    jobject reflect_method;
+    mirror::AbstractMethod* method;
     if (m->IsConstructor()) {
-      reflect_method = env->AllocObject(WellKnownClasses::java_lang_reflect_Constructor);
+      method = mirror::Constructor::CreateFromArtMethod(soa.Self(), m);
     } else {
-      reflect_method = env->AllocObject(WellKnownClasses::java_lang_reflect_Method);
+      method = mirror::Method::CreateFromArtMethod(soa.Self(), m);
     }
-    if (env->ExceptionCheck()) {
-      return nullptr;
-    }
-    SetObjectField(env, reflect_method,
-                   WellKnownClasses::java_lang_reflect_AbstractMethod_artMethod, art_method.get());
-    return reflect_method;
+    return soa.AddLocalReference<jobject>(method);
   }
 
   static jobject ToReflectedField(JNIEnv* env, jclass, jfieldID fid, jboolean) {
diff --git a/runtime/mirror/abstract_method.cc b/runtime/mirror/abstract_method.cc
new file mode 100644
index 0000000..81c656b
--- /dev/null
+++ b/runtime/mirror/abstract_method.cc
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "abstract_method.h"
+
+#include "mirror/art_method-inl.h"
+
+namespace art {
+namespace mirror {
+
+bool AbstractMethod::CreateFromArtMethod(mirror::ArtMethod* method) {
+  auto* interface_method = method->GetInterfaceMethodIfProxy();
+  SetFieldObject<false>(ArtMethodOffset(), method);
+  SetFieldObject<false>(DeclaringClassOffset(), method->GetDeclaringClass());
+  SetFieldObject<false>(
+      DeclaringClassOfOverriddenMethodOffset(), interface_method->GetDeclaringClass());
+  SetField32<false>(AccessFlagsOffset(), method->GetAccessFlags());
+  SetField32<false>(DexMethodIndexOffset(), method->GetDexMethodIndex());
+  return true;
+}
+
+mirror::ArtMethod* AbstractMethod::GetArtMethod() {
+  return GetFieldObject<mirror::ArtMethod>(ArtMethodOffset());
+}
+
+mirror::Class* AbstractMethod::GetDeclaringClass() {
+  return GetFieldObject<mirror::Class>(DeclaringClassOffset());
+}
+
+}  // namespace mirror
+}  // namespace art
diff --git a/runtime/mirror/abstract_method.h b/runtime/mirror/abstract_method.h
new file mode 100644
index 0000000..ef51d7f
--- /dev/null
+++ b/runtime/mirror/abstract_method.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_MIRROR_ABSTRACT_METHOD_H_
+#define ART_RUNTIME_MIRROR_ABSTRACT_METHOD_H_
+
+#include "accessible_object.h"
+#include "gc_root.h"
+#include "object.h"
+#include "object_callbacks.h"
+#include "read_barrier_option.h"
+
+namespace art {
+
+struct AbstractMethodOffsets;
+
+namespace mirror {
+
+class ArtMethod;
+
+// C++ mirror of java.lang.reflect.AbstractMethod.
+class MANAGED AbstractMethod : public AccessibleObject {
+ public:
+  // Called from Constructor::CreateFromArtMethod, Method::CreateFromArtMethod.
+  bool CreateFromArtMethod(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  mirror::ArtMethod* GetArtMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  mirror::Class* GetDeclaringClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ private:
+  static MemberOffset ArtMethodOffset() {
+    return MemberOffset(OFFSETOF_MEMBER(AbstractMethod, art_method_));
+  }
+  static MemberOffset DeclaringClassOffset() {
+    return MemberOffset(OFFSETOF_MEMBER(AbstractMethod, declaring_class_));
+  }
+  static MemberOffset DeclaringClassOfOverriddenMethodOffset() {
+    return MemberOffset(OFFSETOF_MEMBER(AbstractMethod, declaring_class_of_overridden_method_));
+  }
+  static MemberOffset AccessFlagsOffset() {
+    return MemberOffset(OFFSETOF_MEMBER(AbstractMethod, access_flags_));
+  }
+  static MemberOffset DexMethodIndexOffset() {
+    return MemberOffset(OFFSETOF_MEMBER(AbstractMethod, dex_method_index_));
+  }
+
+  HeapReference<mirror::ArtMethod> art_method_;
+  HeapReference<mirror::Class> declaring_class_;
+  HeapReference<mirror::Class> declaring_class_of_overridden_method_;
+  uint32_t access_flags_;
+  uint32_t dex_method_index_;
+
+  friend struct art::AbstractMethodOffsets;  // for verifying offset information
+  DISALLOW_IMPLICIT_CONSTRUCTORS(AbstractMethod);
+};
+
+}  // namespace mirror
+}  // namespace art
+
+#endif  // ART_RUNTIME_MIRROR_ABSTRACT_METHOD_H_
diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h
index a300d52..5fc96ad 100644
--- a/runtime/mirror/art_method-inl.h
+++ b/runtime/mirror/art_method-inl.h
@@ -36,7 +36,7 @@
 namespace mirror {
 
 inline uint32_t ArtMethod::ClassSize() {
-  uint32_t vtable_entries = Object::kVTableLength + 7;
+  uint32_t vtable_entries = Object::kVTableLength;
   return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0);
 }
 
diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc
index 92aea1f..9483ba6 100644
--- a/runtime/mirror/art_method.cc
+++ b/runtime/mirror/art_method.cc
@@ -16,6 +16,7 @@
 
 #include "art_method.h"
 
+#include "abstract_method.h"
 #include "arch/context.h"
 #include "art_field-inl.h"
 #include "art_method-inl.h"
@@ -53,14 +54,11 @@
 
 ArtMethod* ArtMethod::FromReflectedMethod(const ScopedObjectAccessAlreadyRunnable& soa,
                                           jobject jlr_method) {
-  ArtField* f =
-      soa.DecodeField(WellKnownClasses::java_lang_reflect_AbstractMethod_artMethod);
-  mirror::ArtMethod* method = f->GetObject(soa.Decode<mirror::Object*>(jlr_method))->AsArtMethod();
-  DCHECK(method != nullptr);
-  return method;
+  auto* abstract_method = soa.Decode<mirror::AbstractMethod*>(jlr_method);
+  DCHECK(abstract_method != nullptr);
+  return abstract_method->GetArtMethod();
 }
 
-
 void ArtMethod::VisitRoots(RootVisitor* visitor) {
   java_lang_reflect_ArtMethod_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
 }
@@ -547,5 +545,31 @@
   RegisterNative(GetJniDlsymLookupStub(), false);
 }
 
+bool ArtMethod::EqualParameters(Handle<mirror::ObjectArray<mirror::Class>> params) {
+  auto* dex_cache = GetDexCache();
+  auto* dex_file = dex_cache->GetDexFile();
+  const auto& method_id = dex_file->GetMethodId(GetDexMethodIndex());
+  const auto& proto_id = dex_file->GetMethodPrototype(method_id);
+  const DexFile::TypeList* proto_params = dex_file->GetProtoParameters(proto_id);
+  auto count = proto_params != nullptr ? proto_params->Size() : 0u;
+  auto param_len = params.Get() != nullptr ? params->GetLength() : 0u;
+  if (param_len != count) {
+    return false;
+  }
+  auto* cl = Runtime::Current()->GetClassLinker();
+  for (size_t i = 0; i < count; ++i) {
+    auto type_idx = proto_params->GetTypeItem(i).type_idx_;
+    auto* type = cl->ResolveType(type_idx, this);
+    if (type == nullptr) {
+      Thread::Current()->AssertPendingException();
+      return false;
+    }
+    if (type != params->GetWithoutChecks(i)) {
+      return false;
+    }
+  }
+  return true;
+}
+
 }  // namespace mirror
 }  // namespace art
diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h
index 55b8068..b899b25 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/mirror/art_method.h
@@ -541,6 +541,10 @@
 
   ALWAYS_INLINE ArtMethod* GetInterfaceMethodIfProxy() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  // May cause thread suspension due to class resolution.
+  bool EqualParameters(Handle<mirror::ObjectArray<mirror::Class>> params)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   static size_t SizeWithoutPointerFields(size_t pointer_size) {
     size_t total = sizeof(ArtMethod) - sizeof(PtrSizedFields);
 #ifdef ART_METHOD_HAS_PADDING_FIELD_ON_64_BIT
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 2afb4af..1739019 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -25,6 +25,7 @@
 #include "dex_file-inl.h"
 #include "gc/accounting/card_table-inl.h"
 #include "handle_scope-inl.h"
+#include "method.h"
 #include "object_array-inl.h"
 #include "object-inl.h"
 #include "runtime.h"
@@ -876,5 +877,26 @@
   return Runtime::Current()->GetClassLinker()->GetDescriptorForProxy(this) == match;
 }
 
+mirror::ArtMethod* Class::GetDeclaredConstructor(
+    Thread* self, Handle<mirror::ObjectArray<mirror::Class>> args) {
+  auto* direct_methods = GetDirectMethods();
+  size_t count = direct_methods != nullptr ? direct_methods->GetLength() : 0u;
+  for (size_t i = 0; i < count; ++i) {
+    auto* m = direct_methods->GetWithoutChecks(i);
+    // Skip <clinit> which is a static constructor, as well as non constructors.
+    if (m->IsStatic() || !m->IsConstructor()) {
+      continue;
+    }
+    // May cause thread suspension and exceptions.
+    if (m->EqualParameters(args)) {
+      return m;
+    }
+    if (self->IsExceptionPending()) {
+      return nullptr;
+    }
+  }
+  return nullptr;
+}
+
 }  // namespace mirror
 }  // namespace art
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 20f2387..5005346 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -47,6 +47,7 @@
 
 class ArtMethod;
 class ClassLoader;
+class Constructor;
 class DexCache;
 class IfTable;
 
@@ -1052,6 +1053,11 @@
     return OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_strings_);
   }
 
+  // May cause thread suspension due to EqualParameters.
+  mirror::ArtMethod* GetDeclaredConstructor(
+      Thread* self, Handle<mirror::ObjectArray<mirror::Class>> args)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   // Used to initialize a class in the allocation code path to ensure it is guarded by a StoreStore
   // fence.
   class InitializeClassVisitor {
diff --git a/runtime/mirror/field.h b/runtime/mirror/field.h
index 9988f84..d927f0c 100644
--- a/runtime/mirror/field.h
+++ b/runtime/mirror/field.h
@@ -82,15 +82,12 @@
   }
 
   static void SetClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  static void SetArrayClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
   static void ResetClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  static void SetArrayClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   static void ResetArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  static void VisitRoots(RootVisitor* visitor)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  static void VisitRoots(RootVisitor* visitor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Slow, try to use only for PrettyField and such.
   ArtField* GetArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/mirror/method.cc b/runtime/mirror/method.cc
new file mode 100644
index 0000000..81530bb
--- /dev/null
+++ b/runtime/mirror/method.cc
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "method.h"
+
+#include "mirror/art_method.h"
+#include "mirror/object-inl.h"
+
+namespace art {
+namespace mirror {
+
+GcRoot<Class> Method::static_class_;
+GcRoot<Class> Method::array_class_;
+GcRoot<Class> Constructor::static_class_;
+GcRoot<Class> Constructor::array_class_;
+
+void Method::SetClass(Class* klass) {
+  CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
+  CHECK(klass != nullptr);
+  static_class_ = GcRoot<Class>(klass);
+}
+
+void Method::ResetClass() {
+  CHECK(!static_class_.IsNull());
+  static_class_ = GcRoot<Class>(nullptr);
+}
+
+void Method::SetArrayClass(Class* klass) {
+  CHECK(array_class_.IsNull()) << array_class_.Read() << " " << klass;
+  CHECK(klass != nullptr);
+  array_class_ = GcRoot<Class>(klass);
+}
+
+void Method::ResetArrayClass() {
+  CHECK(!array_class_.IsNull());
+  array_class_ = GcRoot<Class>(nullptr);
+}
+
+Method* Method::CreateFromArtMethod(Thread* self, mirror::ArtMethod* method) {
+  DCHECK(!method->IsConstructor()) << PrettyMethod(method);
+  auto* ret = down_cast<Method*>(StaticClass()->AllocObject(self));
+  if (LIKELY(ret != nullptr)) {
+    static_cast<AbstractMethod*>(ret)->CreateFromArtMethod(method);
+  }
+  return ret;
+}
+
+void Method::VisitRoots(RootVisitor* visitor) {
+  static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
+  array_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
+}
+
+void Constructor::SetClass(Class* klass) {
+  CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
+  CHECK(klass != nullptr);
+  static_class_ = GcRoot<Class>(klass);
+}
+
+void Constructor::ResetClass() {
+  CHECK(!static_class_.IsNull());
+  static_class_ = GcRoot<Class>(nullptr);
+}
+
+void Constructor::SetArrayClass(Class* klass) {
+  CHECK(array_class_.IsNull()) << array_class_.Read() << " " << klass;
+  CHECK(klass != nullptr);
+  array_class_ = GcRoot<Class>(klass);
+}
+
+void Constructor::ResetArrayClass() {
+  CHECK(!array_class_.IsNull());
+  array_class_ = GcRoot<Class>(nullptr);
+}
+
+void Constructor::VisitRoots(RootVisitor* visitor) {
+  static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
+  array_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
+}
+
+Constructor* Constructor::CreateFromArtMethod(Thread* self, mirror::ArtMethod* method) {
+  DCHECK(method->IsConstructor()) << PrettyMethod(method);
+  auto* ret = down_cast<Constructor*>(StaticClass()->AllocObject(self));
+  if (LIKELY(ret != nullptr)) {
+    static_cast<AbstractMethod*>(ret)->CreateFromArtMethod(method);
+  }
+  return ret;
+}
+
+}  // namespace mirror
+}  // namespace art
diff --git a/runtime/mirror/method.h b/runtime/mirror/method.h
new file mode 100644
index 0000000..88100f0
--- /dev/null
+++ b/runtime/mirror/method.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_MIRROR_METHOD_H_
+#define ART_RUNTIME_MIRROR_METHOD_H_
+
+#include "abstract_method.h"
+#include "gc_root.h"
+
+namespace art {
+namespace mirror {
+
+class Class;
+
+// C++ mirror of java.lang.reflect.Method.
+class MANAGED Method : public AbstractMethod {
+ public:
+  static Method* CreateFromArtMethod(Thread* self, mirror::ArtMethod* method)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  static mirror::Class* StaticClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return static_class_.Read();
+  }
+
+  static void SetClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  static void ResetClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  static mirror::Class* ArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return array_class_.Read();
+  }
+
+  static void SetArrayClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  static void ResetArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  static void VisitRoots(RootVisitor* visitor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ private:
+  static GcRoot<Class> static_class_;  // java.lang.reflect.Method.class.
+  static GcRoot<Class> array_class_;  // [java.lang.reflect.Method.class.
+
+  DISALLOW_COPY_AND_ASSIGN(Method);
+};
+
+// C++ mirror of java.lang.reflect.Constructor.
+class MANAGED Constructor: public AbstractMethod {
+ public:
+  static Constructor* CreateFromArtMethod(Thread* self, mirror::ArtMethod* method)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  static mirror::Class* StaticClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return static_class_.Read();
+  }
+
+  static void SetClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  static void ResetClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  static mirror::Class* ArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return array_class_.Read();
+  }
+
+  static void SetArrayClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  static void ResetArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  static void VisitRoots(RootVisitor* visitor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ private:
+  static GcRoot<Class> static_class_;  // java.lang.reflect.Constructor.class.
+  static GcRoot<Class> array_class_;  // [java.lang.reflect.Constructor.class.
+
+  DISALLOW_COPY_AND_ASSIGN(Constructor);
+};
+
+}  // namespace mirror
+}  // namespace art
+
+#endif  // ART_RUNTIME_MIRROR_METHOD_H_
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index 5ad18f8..51a897d 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -25,6 +25,7 @@
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/field-inl.h"
+#include "mirror/method.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
 #include "mirror/string-inl.h"
@@ -91,18 +92,6 @@
   return soa.AddLocalReference<jclass>(c.Get());
 }
 
-static jobject Class_findOverriddenMethodIfProxy(JNIEnv* env, jclass, jobject art_method) {
-  ScopedFastNativeObjectAccess soa(env);
-  mirror::ArtMethod* method = soa.Decode<mirror::ArtMethod*>(art_method);
-  mirror::Class* declaring_klass = method->GetDeclaringClass();
-  if (!declaring_klass->IsProxyClass()) {
-    return art_method;
-  }
-  uint32_t dex_method_index = method->GetDexMethodIndex();
-  mirror::ArtMethod* overriden_method = method->GetDexCacheResolvedMethods()->Get(dex_method_index);
-  return soa.AddLocalReference<jobject>(overriden_method);
-}
-
 static jstring Class_getNameNative(JNIEnv* env, jobject javaThis) {
   ScopedFastNativeObjectAccess soa(env);
   StackHandleScope<1> hs(soa.Self());
@@ -252,7 +241,7 @@
 static jobject Class_getDeclaredField(JNIEnv* env, jobject javaThis, jstring name) {
   ScopedFastNativeObjectAccess soa(env);
   auto* name_string = soa.Decode<mirror::String*>(name);
-  if (name == nullptr) {
+  if (name_string == nullptr) {
     ThrowNullPointerException("name == null");
     return nullptr;
   }
@@ -269,17 +258,222 @@
   return soa.AddLocalReference<jobject>(result);
 }
 
+static jobject Class_getDeclaredConstructorInternal(
+    JNIEnv* env, jobject javaThis, jobjectArray args) {
+  ScopedFastNativeObjectAccess soa(env);
+  auto* klass = DecodeClass(soa, javaThis);
+  auto* params = soa.Decode<mirror::ObjectArray<mirror::Class>*>(args);
+  StackHandleScope<1> hs(soa.Self());
+  auto* declared_constructor = klass->GetDeclaredConstructor(soa.Self(), hs.NewHandle(params));
+  if (declared_constructor != nullptr) {
+    return soa.AddLocalReference<jobject>(
+        mirror::Constructor::CreateFromArtMethod(soa.Self(), declared_constructor));
+  }
+  return nullptr;
+}
+
+static ALWAYS_INLINE inline bool MethodMatchesConstructor(mirror::ArtMethod* m, bool public_only)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  DCHECK(m != nullptr);
+  return (!public_only || m->IsPublic()) && !m->IsStatic() && m->IsConstructor();
+}
+
+static jobjectArray Class_getDeclaredConstructorsInternal(
+    JNIEnv* env, jobject javaThis, jboolean publicOnly) {
+  ScopedFastNativeObjectAccess soa(env);
+  auto* klass = DecodeClass(soa, javaThis);
+  StackHandleScope<2> hs(soa.Self());
+  auto h_direct_methods = hs.NewHandle(klass->GetDirectMethods());
+  size_t constructor_count = 0;
+  auto count = h_direct_methods.Get() != nullptr ? h_direct_methods->GetLength() : 0u;
+  // Two pass approach for speed.
+  for (size_t i = 0; i < count; ++i) {
+    constructor_count += MethodMatchesConstructor(h_direct_methods->GetWithoutChecks(i),
+                                                  publicOnly != JNI_FALSE) ? 1u : 0u;
+  }
+  auto h_constructors = hs.NewHandle(mirror::ObjectArray<mirror::Constructor>::Alloc(
+      soa.Self(), mirror::Constructor::ArrayClass(), constructor_count));
+  if (UNLIKELY(h_constructors.Get() == nullptr)) {
+    soa.Self()->AssertPendingException();
+    return nullptr;
+  }
+  constructor_count = 0;
+  for (size_t i = 0; i < count; ++i) {
+    auto* method = h_direct_methods->GetWithoutChecks(i);
+    if (MethodMatchesConstructor(method, publicOnly != JNI_FALSE)) {
+      auto* constructor = mirror::Constructor::CreateFromArtMethod(soa.Self(), method);
+      if (UNLIKELY(constructor == nullptr)) {
+        soa.Self()->AssertPendingException();
+        return nullptr;
+      }
+      h_constructors->SetWithoutChecks<false>(constructor_count++, constructor);
+    }
+  }
+  return soa.AddLocalReference<jobjectArray>(h_constructors.Get());
+}
+
+static jobject Class_getDeclaredMethodInternal(JNIEnv* env, jobject javaThis,
+                                               jobject name, jobjectArray args) {
+  // Covariant return types permit the class to define multiple
+  // methods with the same name and parameter types. Prefer to
+  // return a non-synthetic method in such situations. We may
+  // still return a synthetic method to handle situations like
+  // escalated visibility. We never return miranda methods that
+  // were synthesized by the runtime.
+  constexpr uint32_t kSkipModifiers = kAccMiranda | kAccSynthetic;
+  ScopedFastNativeObjectAccess soa(env);
+  StackHandleScope<5> hs(soa.Self());
+  auto h_method_name = hs.NewHandle(soa.Decode<mirror::String*>(name));
+  if (UNLIKELY(h_method_name.Get() == nullptr)) {
+    ThrowNullPointerException("name == null");
+    return nullptr;
+  }
+  auto h_args = hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Class>*>(args));
+  auto* klass = DecodeClass(soa, javaThis);
+  mirror::ArtMethod* result = nullptr;
+  auto* virtual_methods = klass->GetVirtualMethods();
+  if (virtual_methods != nullptr) {
+    auto h_virtual_methods = hs.NewHandle(virtual_methods);
+    for (size_t i = 0, count = virtual_methods->GetLength(); i < count; ++i) {
+      auto* m = h_virtual_methods->GetWithoutChecks(i);
+      auto* np_method = m->GetInterfaceMethodIfProxy();
+      // May cause thread suspension.
+      mirror::String* np_name = np_method->GetNameAsString(soa.Self());
+      if (!np_name->Equals(h_method_name.Get()) || !np_method->EqualParameters(h_args)) {
+        if (UNLIKELY(soa.Self()->IsExceptionPending())) {
+          return nullptr;
+        }
+        continue;
+      }
+      auto modifiers = m->GetAccessFlags();
+      if ((modifiers & kSkipModifiers) == 0) {
+        return soa.AddLocalReference<jobject>(mirror::Method::CreateFromArtMethod(soa.Self(), m));
+      }
+      if ((modifiers & kAccMiranda) == 0) {
+        result = m;  // Remember as potential result if it's not a miranda method.
+      }
+    }
+  }
+  if (result == nullptr) {
+    auto* direct_methods = klass->GetDirectMethods();
+    if (direct_methods != nullptr) {
+      auto h_direct_methods = hs.NewHandle(direct_methods);
+      for (size_t i = 0, count = direct_methods->GetLength(); i < count; ++i) {
+        auto* m = h_direct_methods->GetWithoutChecks(i);
+        auto modifiers = m->GetAccessFlags();
+        if ((modifiers & kAccConstructor) != 0) {
+          continue;
+        }
+        auto* np_method = m->GetInterfaceMethodIfProxy();
+        // May cause thread suspension.
+        mirror::String* np_name = np_method ->GetNameAsString(soa.Self());
+        if (np_name == nullptr) {
+          soa.Self()->AssertPendingException();
+          return nullptr;
+        }
+        if (!np_name->Equals(h_method_name.Get()) || !np_method->EqualParameters(h_args)) {
+          if (UNLIKELY(soa.Self()->IsExceptionPending())) {
+            return nullptr;
+          }
+          continue;
+        }
+        if ((modifiers & kSkipModifiers) == 0) {
+          return soa.AddLocalReference<jobject>(mirror::Method::CreateFromArtMethod(
+              soa.Self(), m));
+        }
+        // Direct methods cannot be miranda methods, so this potential result must be synthetic.
+        result = m;
+      }
+    }
+  }
+  return result != nullptr ?
+      soa.AddLocalReference<jobject>(mirror::Method::CreateFromArtMethod(soa.Self(), result)) :
+      nullptr;
+}
+
+jobjectArray Class_getDeclaredMethodsUnchecked(JNIEnv* env, jobject javaThis,
+                                               jboolean publicOnly) {
+  ScopedFastNativeObjectAccess soa(env);
+  StackHandleScope<5> hs(soa.Self());
+  auto* klass = DecodeClass(soa, javaThis);
+  auto virtual_methods = hs.NewHandle(klass->GetVirtualMethods());
+  auto direct_methods = hs.NewHandle(klass->GetDirectMethods());
+  size_t num_methods = 0;
+  if (virtual_methods.Get() != nullptr) {
+    for (size_t i = 0, count = virtual_methods->GetLength(); i < count; ++i) {
+      auto* m = virtual_methods->GetWithoutChecks(i);
+      auto modifiers = m->GetAccessFlags();
+      if ((publicOnly == JNI_FALSE || (modifiers & kAccPublic) != 0) &&
+          (modifiers & kAccMiranda) == 0) {
+        ++num_methods;
+      }
+    }
+  }
+  if (direct_methods.Get() != nullptr) {
+    for (size_t i = 0, count = direct_methods->GetLength(); i < count; ++i) {
+      auto* m = direct_methods->GetWithoutChecks(i);
+      auto modifiers = m->GetAccessFlags();
+      // Add non-constructor direct/static methods.
+      if ((publicOnly == JNI_FALSE || (modifiers & kAccPublic) != 0) &&
+          (modifiers & kAccConstructor) == 0) {
+        ++num_methods;
+      }
+    }
+  }
+  auto ret = hs.NewHandle(mirror::ObjectArray<mirror::Method>::Alloc(
+      soa.Self(), mirror::Method::ArrayClass(), num_methods));
+  num_methods = 0;
+  if (virtual_methods.Get() != nullptr) {
+    for (size_t i = 0, count = virtual_methods->GetLength(); i < count; ++i) {
+      auto* m = virtual_methods->GetWithoutChecks(i);
+      auto modifiers = m->GetAccessFlags();
+      if ((publicOnly == JNI_FALSE || (modifiers & kAccPublic) != 0) &&
+          (modifiers & kAccMiranda) == 0) {
+        auto* method = mirror::Method::CreateFromArtMethod(soa.Self(), m);
+        if (method == nullptr) {
+          soa.Self()->AssertPendingException();
+          return nullptr;
+        }
+        ret->SetWithoutChecks<false>(num_methods++, method);
+      }
+    }
+  }
+  if (direct_methods.Get() != nullptr) {
+    for (size_t i = 0, count = direct_methods->GetLength(); i < count; ++i) {
+      auto* m = direct_methods->GetWithoutChecks(i);
+      auto modifiers = m->GetAccessFlags();
+      // Add non-constructor direct/static methods.
+      if ((publicOnly == JNI_FALSE || (modifiers & kAccPublic) != 0) &&
+          (modifiers & kAccConstructor) == 0) {
+        auto* method = mirror::Method::CreateFromArtMethod(soa.Self(), m);
+        if (method == nullptr) {
+          soa.Self()->AssertPendingException();
+          return nullptr;
+        }
+        ret->SetWithoutChecks<false>(num_methods++, method);
+      }
+    }
+  }
+  return soa.AddLocalReference<jobjectArray>(ret.Get());
+}
+
 static JNINativeMethod gMethods[] = {
-  NATIVE_METHOD(Class, classForName, "!(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"),
-  NATIVE_METHOD(Class, findOverriddenMethodIfProxy,
-                "!(Ljava/lang/reflect/ArtMethod;)Ljava/lang/reflect/ArtMethod;"),
+  NATIVE_METHOD(Class, classForName,
+                "!(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"),
+  NATIVE_METHOD(Class, getDeclaredConstructorInternal,
+                "!([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;"),
+  NATIVE_METHOD(Class, getDeclaredConstructorsInternal, "!(Z)[Ljava/lang/reflect/Constructor;"),
+  NATIVE_METHOD(Class, getDeclaredField, "!(Ljava/lang/String;)Ljava/lang/reflect/Field;"),
+  NATIVE_METHOD(Class, getDeclaredFieldInternal, "!(Ljava/lang/String;)Ljava/lang/reflect/Field;"),
+  NATIVE_METHOD(Class, getDeclaredFields, "!()[Ljava/lang/reflect/Field;"),
+  NATIVE_METHOD(Class, getDeclaredFieldsUnchecked, "!(Z)[Ljava/lang/reflect/Field;"),
+  NATIVE_METHOD(Class, getDeclaredMethodInternal,
+                "!(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;"),
+  NATIVE_METHOD(Class, getDeclaredMethodsUnchecked,
+                  "!(Z)[Ljava/lang/reflect/Method;"),
   NATIVE_METHOD(Class, getNameNative, "!()Ljava/lang/String;"),
   NATIVE_METHOD(Class, getProxyInterfaces, "!()[Ljava/lang/Class;"),
-  NATIVE_METHOD(Class, getDeclaredFields, "!()[Ljava/lang/reflect/Field;"),
   NATIVE_METHOD(Class, getPublicDeclaredFields, "!()[Ljava/lang/reflect/Field;"),
-  NATIVE_METHOD(Class, getDeclaredFieldsUnchecked, "!(Z)[Ljava/lang/reflect/Field;"),
-  NATIVE_METHOD(Class, getDeclaredFieldInternal, "!(Ljava/lang/String;)Ljava/lang/reflect/Field;"),
-  NATIVE_METHOD(Class, getDeclaredField, "!(Ljava/lang/String;)Ljava/lang/reflect/Field;"),
 };
 
 void register_java_lang_Class(JNIEnv* env) {
diff --git a/runtime/native/java_lang_reflect_Constructor.cc b/runtime/native/java_lang_reflect_Constructor.cc
index 5e1a4c5..c33f81a 100644
--- a/runtime/native/java_lang_reflect_Constructor.cc
+++ b/runtime/native/java_lang_reflect_Constructor.cc
@@ -21,6 +21,7 @@
 #include "mirror/art_method.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
+#include "mirror/method.h"
 #include "mirror/object-inl.h"
 #include "reflection.h"
 #include "scoped_fast_native_object_access.h"
@@ -28,17 +29,10 @@
 
 namespace art {
 
-/*
- * We get here through Constructor.newInstance().  The Constructor object
- * would not be available if the constructor weren't public (per the
- * definition of Class.getConstructor), so we can skip the method access
- * check.  We can also safely assume the constructor isn't associated
- * with an interface, array, or primitive class.
- */
-static jobject Constructor_newInstance(JNIEnv* env, jobject javaMethod, jobjectArray javaArgs,
-                                       jboolean accessible) {
+static ALWAYS_INLINE inline jobject NewInstanceHelper(
+    JNIEnv* env, jobject javaMethod, jobjectArray javaArgs, size_t num_frames) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::ArtMethod* m = mirror::ArtMethod::FromReflectedMethod(soa, javaMethod);
+  mirror::Method* m = soa.Decode<mirror::Method*>(javaMethod);
   StackHandleScope<1> hs(soa.Self());
   Handle<mirror::Class> c(hs.NewHandle(m->GetDeclaringClass()));
   if (UNLIKELY(c->IsAbstract())) {
@@ -67,14 +61,31 @@
   }
 
   jobject javaReceiver = soa.AddLocalReference<jobject>(receiver);
-  InvokeMethod(soa, javaMethod, javaReceiver, javaArgs, (accessible == JNI_TRUE));
+  InvokeMethod(soa, javaMethod, javaReceiver, javaArgs, num_frames);
 
   // Constructors are ()V methods, so we shouldn't touch the result of InvokeMethod.
   return javaReceiver;
 }
 
+/*
+ * We get here through Constructor.newInstance().  The Constructor object
+ * would not be available if the constructor weren't public (per the
+ * definition of Class.getConstructor), so we can skip the method access
+ * check.  We can also safely assume the constructor isn't associated
+ * with an interface, array, or primitive class.
+ */
+static jobject Constructor_newInstance(JNIEnv* env, jobject javaMethod, jobjectArray javaArgs) {
+  return NewInstanceHelper(env, javaMethod, javaArgs, 1);
+}
+
+static jobject Constructor_newInstanceTwoFrames(JNIEnv* env, jobject javaMethod,
+                                                jobjectArray javaArgs) {
+  return NewInstanceHelper(env, javaMethod, javaArgs, 2);
+}
+
 static JNINativeMethod gMethods[] = {
-  NATIVE_METHOD(Constructor, newInstance, "!([Ljava/lang/Object;Z)Ljava/lang/Object;"),
+  NATIVE_METHOD(Constructor, newInstance, "!([Ljava/lang/Object;)Ljava/lang/Object;"),
+  NATIVE_METHOD(Constructor, newInstanceTwoFrames, "!([Ljava/lang/Object;)Ljava/lang/Object;"),
 };
 
 void register_java_lang_reflect_Constructor(JNIEnv* env) {
diff --git a/runtime/native/java_lang_reflect_Method.cc b/runtime/native/java_lang_reflect_Method.cc
index 9859746..c20d832 100644
--- a/runtime/native/java_lang_reflect_Method.cc
+++ b/runtime/native/java_lang_reflect_Method.cc
@@ -30,9 +30,9 @@
 namespace art {
 
 static jobject Method_invoke(JNIEnv* env, jobject javaMethod, jobject javaReceiver,
-                             jobject javaArgs, jboolean accessible) {
+                             jobject javaArgs) {
   ScopedFastNativeObjectAccess soa(env);
-  return InvokeMethod(soa, javaMethod, javaReceiver, javaArgs, (accessible == JNI_TRUE));
+  return InvokeMethod(soa, javaMethod, javaReceiver, javaArgs);
 }
 
 static jobject Method_getExceptionTypesNative(JNIEnv* env, jobject javaMethod) {
@@ -55,7 +55,7 @@
 }
 
 static JNINativeMethod gMethods[] = {
-  NATIVE_METHOD(Method, invoke, "!(Ljava/lang/Object;[Ljava/lang/Object;Z)Ljava/lang/Object;"),
+  NATIVE_METHOD(Method, invoke, "!(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"),
   NATIVE_METHOD(Method, getExceptionTypesNative, "!()[Ljava/lang/Class;"),
 };
 
diff --git a/runtime/native/java_lang_reflect_Proxy.cc b/runtime/native/java_lang_reflect_Proxy.cc
index baf8b24..4a6ab40 100644
--- a/runtime/native/java_lang_reflect_Proxy.cc
+++ b/runtime/native/java_lang_reflect_Proxy.cc
@@ -30,13 +30,12 @@
                                   jobject loader, jobjectArray methods, jobjectArray throws) {
   ScopedFastNativeObjectAccess soa(env);
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  mirror::Class* result = class_linker->CreateProxyClass(soa, name, interfaces, loader, methods,
-                                                         throws);
-  return soa.AddLocalReference<jclass>(result);
+  return soa.AddLocalReference<jclass>(class_linker->CreateProxyClass(
+      soa, name, interfaces, loader, methods, throws));
 }
 
 static JNINativeMethod gMethods[] = {
-  NATIVE_METHOD(Proxy, generateProxy, "!(Ljava/lang/String;[Ljava/lang/Class;Ljava/lang/ClassLoader;[Ljava/lang/reflect/ArtMethod;[[Ljava/lang/Class;)Ljava/lang/Class;"),
+  NATIVE_METHOD(Proxy, generateProxy, "!(Ljava/lang/String;[Ljava/lang/Class;Ljava/lang/ClassLoader;[Ljava/lang/reflect/Method;[[Ljava/lang/Class;)Ljava/lang/Class;"),
 };
 
 void register_java_lang_reflect_Proxy(JNIEnv* env) {
diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc
index 6061f73..b471293 100644
--- a/runtime/proxy_test.cc
+++ b/runtime/proxy_test.cc
@@ -20,6 +20,7 @@
 #include "art_field-inl.h"
 #include "class_linker-inl.h"
 #include "common_compiler_test.h"
+#include "mirror/method.h"
 #include "scoped_thread_state_change.h"
 
 namespace art {
@@ -53,41 +54,34 @@
       mirror::ObjectArray<mirror::ArtMethod>* virtual_methods = interface->GetVirtualMethods();
       methods_count += (virtual_methods == nullptr) ? 0 : virtual_methods->GetLength();
     }
-    jclass javaLangReflectArtMethod =
-        soa.AddLocalReference<jclass>(mirror::ArtMethod::GetJavaLangReflectArtMethod());
-    jobjectArray proxyClassMethods = soa.Env()->NewObjectArray(methods_count,
-                                                               javaLangReflectArtMethod, nullptr);
+    jobjectArray proxyClassMethods = soa.Env()->NewObjectArray(
+        methods_count, soa.AddLocalReference<jclass>(mirror::Method::StaticClass()), nullptr);
     soa.Self()->AssertNoPendingException();
 
-    // Fill the method array
-    mirror::ArtMethod* equalsMethod = javaLangObject->FindDeclaredVirtualMethod("equals",
-                                                                                "(Ljava/lang/Object;)Z");
-    mirror::ArtMethod* hashCodeMethod = javaLangObject->FindDeclaredVirtualMethod("hashCode",
-                                                                                  "()I");
-    mirror::ArtMethod* toStringMethod = javaLangObject->FindDeclaredVirtualMethod("toString",
-                                                                                  "()Ljava/lang/String;");
-    CHECK(equalsMethod != nullptr);
-    CHECK(hashCodeMethod != nullptr);
-    CHECK(toStringMethod != nullptr);
-
     jsize array_index = 0;
-    // Adds Object methods.
-    soa.Env()->SetObjectArrayElement(proxyClassMethods, array_index++,
-                                     soa.AddLocalReference<jobject>(equalsMethod));
-    soa.Env()->SetObjectArrayElement(proxyClassMethods, array_index++,
-                                     soa.AddLocalReference<jobject>(hashCodeMethod));
-    soa.Env()->SetObjectArrayElement(proxyClassMethods, array_index++,
-                                     soa.AddLocalReference<jobject>(toStringMethod));
-
+    // Fill the method array
+    mirror::ArtMethod* method = javaLangObject->FindDeclaredVirtualMethod(
+        "equals", "(Ljava/lang/Object;)Z");
+    CHECK(method != nullptr);
+    soa.Env()->SetObjectArrayElement(
+        proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
+            mirror::Method::CreateFromArtMethod(soa.Self(), method)));
+    method = javaLangObject->FindDeclaredVirtualMethod("hashCode", "()I");
+    CHECK(method != nullptr);
+    soa.Env()->SetObjectArrayElement(
+        proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
+            mirror::Method::CreateFromArtMethod(soa.Self(), method)));
+    method = javaLangObject->FindDeclaredVirtualMethod("toString", "()Ljava/lang/String;");
+    CHECK(method != nullptr);
+    soa.Env()->SetObjectArrayElement(
+        proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
+            mirror::Method::CreateFromArtMethod(soa.Self(), method)));
     // Now adds all interfaces virtual methods.
     for (mirror::Class* interface : interfaces) {
-      mirror::ObjectArray<mirror::ArtMethod>* virtual_methods = interface->GetVirtualMethods();
-      if (virtual_methods != nullptr) {
-        for (int32_t mth_index = 0; mth_index < virtual_methods->GetLength(); ++mth_index) {
-          mirror::ArtMethod* method = virtual_methods->Get(mth_index);
-          soa.Env()->SetObjectArrayElement(proxyClassMethods, array_index++,
-                                           soa.AddLocalReference<jobject>(method));
-        }
+      for (int32_t i = 0, count = interface->NumVirtualMethods(); i < count; ++i) {
+        soa.Env()->SetObjectArrayElement(
+            proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
+                mirror::Method::CreateFromArtMethod(soa.Self(), interface->GetVirtualMethod(i))));
       }
     }
     CHECK_EQ(array_index, methods_count);
@@ -96,10 +90,9 @@
     jobjectArray proxyClassThrows = soa.Env()->NewObjectArray(0, javaLangClass, nullptr);
     soa.Self()->AssertNoPendingException();
 
-    mirror::Class* proxyClass = class_linker_->CreateProxyClass(soa,
-                                                                soa.Env()->NewStringUTF(className),
-                                                                proxyClassInterfaces, jclass_loader,
-                                                                proxyClassMethods, proxyClassThrows);
+    mirror::Class* proxyClass = class_linker_->CreateProxyClass(
+        soa, soa.Env()->NewStringUTF(className), proxyClassInterfaces, jclass_loader,
+        proxyClassMethods, proxyClassThrows);
     soa.Self()->AssertNoPendingException();
     return proxyClass;
   }
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 3e1315c..e546738 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -22,6 +22,7 @@
 #include "dex_file-inl.h"
 #include "entrypoints/entrypoint_utils.h"
 #include "jni_internal.h"
+#include "mirror/abstract_method.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/object_array-inl.h"
@@ -537,7 +538,7 @@
 }
 
 jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject javaMethod,
-                     jobject javaReceiver, jobject javaArgs, bool accessible) {
+                     jobject javaReceiver, jobject javaArgs, size_t num_frames) {
   // We want to make sure that the stack is not within a small distance from the
   // protected region in case we are calling into a leaf function whose stack
   // check has been elided.
@@ -547,7 +548,9 @@
     return nullptr;
   }
 
-  mirror::ArtMethod* m = mirror::ArtMethod::FromReflectedMethod(soa, javaMethod);
+  auto* abstract_method = soa.Decode<mirror::AbstractMethod*>(javaMethod);
+  const bool accessible = abstract_method->IsAccessible();
+  mirror::ArtMethod* m = abstract_method->GetArtMethod();
 
   mirror::Class* declaring_class = m->GetDeclaringClass();
   if (UNLIKELY(!declaring_class->IsInitialized())) {
@@ -572,8 +575,7 @@
   }
 
   // Get our arrays of arguments and their types, and check they're the same size.
-  mirror::ObjectArray<mirror::Object>* objects =
-      soa.Decode<mirror::ObjectArray<mirror::Object>*>(javaArgs);
+  auto* objects = soa.Decode<mirror::ObjectArray<mirror::Object>*>(javaArgs);
   const DexFile::TypeList* classes = m->GetParameterTypeList();
   uint32_t classes_size = (classes == nullptr) ? 0 : classes->Size();
   uint32_t arg_count = (objects != nullptr) ? objects->GetLength() : 0;
@@ -586,7 +588,7 @@
   // If method is not set to be accessible, verify it can be accessed by the caller.
   mirror::Class* calling_class = nullptr;
   if (!accessible && !VerifyAccess(soa.Self(), receiver, declaring_class, m->GetAccessFlags(),
-                                   &calling_class, 2)) {
+                                   &calling_class, num_frames)) {
     ThrowIllegalAccessException(
         StringPrintf("Class %s cannot access %s method %s of class %s",
             calling_class == nullptr ? "null" : PrettyClass(calling_class).c_str(),
diff --git a/runtime/reflection.h b/runtime/reflection.h
index c2d406a..c63f858 100644
--- a/runtime/reflection.h
+++ b/runtime/reflection.h
@@ -65,8 +65,9 @@
                            JValue* result)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+// num_frames is number of frames we look up for access check.
 jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject method, jobject receiver,
-                     jobject args, bool accessible)
+                     jobject args, size_t num_frames = 1)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 ALWAYS_INLINE bool VerifyObjectIsClass(mirror::Object* o, mirror::Class* c)
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 7bebb96..2fc8d20 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -77,6 +77,7 @@
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/field.h"
+#include "mirror/method.h"
 #include "mirror/stack_trace_element.h"
 #include "mirror/throwable.h"
 #include "monitor.h"
@@ -1308,7 +1309,9 @@
   // need to be visited once per GC since they never change.
   mirror::ArtMethod::VisitRoots(visitor);
   mirror::Class::VisitRoots(visitor);
+  mirror::Constructor::VisitRoots(visitor);
   mirror::Reference::VisitRoots(visitor);
+  mirror::Method::VisitRoots(visitor);
   mirror::StackTraceElement::VisitRoots(visitor);
   mirror::String::VisitRoots(visitor);
   mirror::Throwable::VisitRoots(visitor);
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index d389244..f57f9c4 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -212,7 +212,7 @@
   ScopedLocalRef<jclass> java_lang_ref_ReferenceQueue(env, env->FindClass("java/lang/ref/ReferenceQueue"));
   java_lang_ref_ReferenceQueue_add = CacheMethod(env, java_lang_ref_ReferenceQueue.get(), true, "add", "(Ljava/lang/ref/Reference;)V");
 
-  java_lang_reflect_Proxy_invoke = CacheMethod(env, java_lang_reflect_Proxy, true, "invoke", "(Ljava/lang/reflect/Proxy;Ljava/lang/reflect/ArtMethod;[Ljava/lang/Object;)Ljava/lang/Object;");
+  java_lang_reflect_Proxy_invoke = CacheMethod(env, java_lang_reflect_Proxy, true, "invoke", "(Ljava/lang/reflect/Proxy;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;");
   java_lang_Thread_init = CacheMethod(env, java_lang_Thread, false, "<init>", "(Ljava/lang/ThreadGroup;Ljava/lang/String;IZ)V");
   java_lang_Thread_run = CacheMethod(env, java_lang_Thread, false, "run", "()V");
   java_lang_Thread__UncaughtExceptionHandler_uncaughtException = CacheMethod(env, java_lang_Thread__UncaughtExceptionHandler, false, "uncaughtException", "(Ljava/lang/Thread;Ljava/lang/Throwable;)V");