Change dex cache to be java object instead of array, add pointer to dex file in dex cache.

Generic clean up to facilitate having GDB macros for Pretty* helper functions.

Improved cleanliness of DexCache since having it as an object array was not the best solution.

Fixed a bug in InOrderWalk caused by ResolveType sometimes allocating classes.

Rename C++ Method to AbstractMethod and add two new classes Constructor, Method which both inherit from AbstractMethod.

Rename done to have the C++ code be closer to the java code.

Change-Id: I4995b4c5e47a3822192b08afa24a639d3b1f4da9
diff --git a/src/check_jni.cc b/src/check_jni.cc
index c53a1e3..5146039 100644
--- a/src/check_jni.cc
+++ b/src/check_jni.cc
@@ -36,7 +36,7 @@
 static void JniAbort(const char* jni_function_name, const char* msg) {
   Thread* self = Thread::Current();
   ScopedObjectAccess soa(self);
-  Method* current_method = self->GetCurrentMethod();
+  AbstractMethod* current_method = self->GetCurrentMethod();
 
   std::ostringstream os;
   os << "JNI DETECTED ERROR IN APPLICATION: " << msg;
@@ -123,7 +123,7 @@
   NULL
 };
 
-static bool ShouldTrace(JavaVMExt* vm, const Method* method)
+static bool ShouldTrace(JavaVMExt* vm, const AbstractMethod* method)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   // If both "-Xcheck:jni" and "-Xjnitrace:" are enabled, we print trace messages
   // when a native method that matches the -Xjnitrace argument calls a JNI function
@@ -276,7 +276,7 @@
    */
   void CheckSig(jmethodID mid, const char* expectedType, bool isStatic)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    Method* m = CheckMethodID(mid);
+    AbstractMethod* m = CheckMethodID(mid);
     if (m == NULL) {
       return;
     }
@@ -324,7 +324,7 @@
    */
   void CheckStaticMethod(jclass java_class, jmethodID mid)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    const Method* m = CheckMethodID(mid);
+    const AbstractMethod* m = CheckMethodID(mid);
     if (m == NULL) {
       return;
     }
@@ -344,7 +344,7 @@
    */
   void CheckVirtualMethod(jobject java_object, jmethodID mid)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    const Method* m = CheckMethodID(mid);
+    const AbstractMethod* m = CheckMethodID(mid);
     if (m == NULL) {
       return;
     }
@@ -395,7 +395,7 @@
       SHARED_LOCKS_REQUIRED (Locks::mutator_lock_) {
     va_list ap;
 
-    const Method* traceMethod = NULL;
+    const AbstractMethod* traceMethod = NULL;
     if ((!soa_.Vm()->trace.empty() || VLOG_IS_ON(third_party_jni)) && has_method_) {
       // We need to guard some of the invocation interface's calls: a bad caller might
       // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
@@ -481,7 +481,7 @@
           StringAppendF(&msg, "%d", i);
         } else if (ch == 'm') { // jmethodID
           jmethodID mid = va_arg(ap, jmethodID);
-          Method* m = reinterpret_cast<Method*>(mid);
+          AbstractMethod* m = reinterpret_cast<AbstractMethod*>(mid);
           msg += PrettyMethod(m);
           if (!entry) {
             StringAppendF(&msg, " (%p)", mid);
@@ -702,12 +702,12 @@
     return f;
   }
 
-  Method* CheckMethodID(jmethodID mid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  AbstractMethod* CheckMethodID(jmethodID mid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     if (mid == NULL) {
       JniAbortF(function_name_, "jmethodID was NULL");
       return NULL;
     }
-    Method* m = soa_.DecodeMethod(mid);
+    AbstractMethod* m = soa_.DecodeMethod(mid);
     if (!Runtime::Current()->GetHeap()->IsHeapAddress(m) || !m->IsMethod()) {
       JniAbortF(function_name_, "invalid jmethodID: %p", mid);
       return NULL;
diff --git a/src/class_linker.cc b/src/class_linker.cc
index f9fbc58..c7c3a33 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -166,11 +166,16 @@
   "[Ljava/lang/Class;",
   "[Ljava/lang/Object;",
   "Ljava/lang/String;",
+  "Ljava/lang/DexCache;",
   "Ljava/lang/ref/Reference;",
   "Ljava/lang/reflect/Constructor;",
   "Ljava/lang/reflect/Field;",
+  "Ljava/lang/reflect/AbstractMethod;",
   "Ljava/lang/reflect/Method;",
   "Ljava/lang/reflect/Proxy;",
+  "[Ljava/lang/String;",
+  "[Ljava/lang/reflect/Field;",
+  "[Ljava/lang/reflect/AbstractMethod;",
   "Ljava/lang/ClassLoader;",
   "Ljava/lang/Throwable;",
   "Ljava/lang/ClassNotFoundException;",
@@ -294,19 +299,17 @@
 
   // now that these are registered, we can use AllocClass() and AllocObjectArray
 
-  // setup boot_class_path_ and register class_path now that we can
-  // use AllocObjectArray to create DexCache instances
-  CHECK_NE(0U, boot_class_path.size());
-  for (size_t i = 0; i != boot_class_path.size(); ++i) {
-    const DexFile* dex_file = boot_class_path[i];
-    CHECK(dex_file != NULL);
-    AppendToBootClassPath(*dex_file);
-  }
+  // Setup DexCache. This can not be done later since AppendToBootClassPath calls AllocDexCache.
+  SirtRef<Class> java_lang_DexCache(AllocClass(java_lang_Class.get(), sizeof(DexCacheClass)));
+  SetClassRoot(kJavaLangDexCache, java_lang_DexCache.get());
+  java_lang_DexCache->SetObjectSize(sizeof(DexCacheClass));
+  java_lang_DexCache->SetStatus(Class::kStatusResolved);
 
-  // Constructor, Field, and Method are necessary so that FindClass can link members
-  SirtRef<Class> java_lang_reflect_Constructor(AllocClass(java_lang_Class.get(), sizeof(MethodClass)));
+  // Constructor, Field, Method, and AbstractMethod are necessary so that FindClass can link members.
+  SirtRef<Class> java_lang_reflect_Constructor(AllocClass(java_lang_Class.get(),
+                                                          sizeof(MethodClass)));
   CHECK(java_lang_reflect_Constructor.get() != NULL);
-  java_lang_reflect_Constructor->SetObjectSize(sizeof(Method));
+  java_lang_reflect_Constructor->SetObjectSize(sizeof(Constructor));
   SetClassRoot(kJavaLangReflectConstructor, java_lang_reflect_Constructor.get());
   java_lang_reflect_Constructor->SetStatus(Class::kStatusResolved);
 
@@ -322,7 +325,37 @@
   java_lang_reflect_Method->SetObjectSize(sizeof(Method));
   SetClassRoot(kJavaLangReflectMethod, java_lang_reflect_Method.get());
   java_lang_reflect_Method->SetStatus(Class::kStatusResolved);
-  Method::SetClasses(java_lang_reflect_Constructor.get(), java_lang_reflect_Method.get());
+
+  SirtRef<Class> java_lang_reflect_AbstractMethod(AllocClass(java_lang_Class.get(),
+                                                             sizeof(MethodClass)));
+  CHECK(java_lang_reflect_AbstractMethod.get() != NULL);
+  java_lang_reflect_AbstractMethod->SetObjectSize(sizeof(AbstractMethod));
+  SetClassRoot(kJavaLangReflectAbstractMethod, java_lang_reflect_AbstractMethod.get());
+  java_lang_reflect_AbstractMethod->SetStatus(Class::kStatusResolved);
+  AbstractMethod::SetClasses(java_lang_reflect_Constructor.get(), java_lang_reflect_Method.get());
+
+  // Set up array classes for string, field, method
+  SirtRef<Class> object_array_string(AllocClass(java_lang_Class.get(), sizeof(Class)));
+  object_array_string->SetComponentType(java_lang_String.get());
+  SetClassRoot(kJavaLangStringArrayClass, object_array_string.get());
+
+  SirtRef<Class> object_array_field(AllocClass(java_lang_Class.get(), sizeof(Class)));
+  object_array_field->SetComponentType(java_lang_reflect_Field.get());
+  SetClassRoot(kJavaLangReflectFieldArrayClass, object_array_field.get());
+
+  SirtRef<Class> object_array_abstract_method(AllocClass(java_lang_Class.get(), sizeof(Class)));
+  object_array_abstract_method->SetComponentType(java_lang_reflect_AbstractMethod.get());
+  SetClassRoot(kJavaLangReflectAbstractMethodArrayClass, object_array_abstract_method.get());
+
+  // setup boot_class_path_ and register class_path now that we can
+  // use AllocObjectArray to create DexCache instances
+  // Needs to be after String, Field, Method arrays since AllocDexCache uses these roots.
+  CHECK_NE(0U, boot_class_path.size());
+  for (size_t i = 0; i != boot_class_path.size(); ++i) {
+    const DexFile* dex_file = boot_class_path[i];
+    CHECK(dex_file != NULL);
+    AppendToBootClassPath(*dex_file);
+  }
 
   // now we can use FindSystemClass
 
@@ -330,7 +363,7 @@
   InitializePrimitiveClass(char_class.get(), Primitive::kPrimChar);
   SetClassRoot(kPrimitiveChar, char_class.get());  // needs descriptor
 
-  // Object and String need to be rerun through FindSystemClass to finish init
+  // Object, String and DexCache need to be rerun through FindSystemClass to finish init
   java_lang_Object->SetStatus(Class::kStatusNotReady);
   Class* Object_class = FindSystemClass("Ljava/lang/Object;");
   CHECK_EQ(java_lang_Object.get(), Object_class);
@@ -339,6 +372,11 @@
   Class* String_class = FindSystemClass("Ljava/lang/String;");
   CHECK_EQ(java_lang_String.get(), String_class);
   CHECK_EQ(java_lang_String->GetObjectSize(), sizeof(String));
+  java_lang_DexCache->SetStatus(Class::kStatusNotReady);
+  Class* DexCache_class = FindSystemClass("Ljava/lang/DexCache;");
+  CHECK_EQ(java_lang_String.get(), String_class);
+  CHECK_EQ(java_lang_DexCache.get(), DexCache_class);
+  CHECK_EQ(java_lang_DexCache->GetObjectSize(), sizeof(DexCache));
 
   // Setup the primitive array type classes - can't be done until Object has a vtable
   SetClassRoot(kBooleanArrayClass, FindSystemClass("[Z"));
@@ -394,6 +432,16 @@
   Class* Class_class = FindSystemClass("Ljava/lang/Class;");
   CHECK_EQ(java_lang_Class.get(), Class_class);
 
+  java_lang_reflect_AbstractMethod->SetStatus(Class::kStatusNotReady);
+  Class* Abstract_method_class = FindSystemClass("Ljava/lang/reflect/AbstractMethod;");
+  CHECK_EQ(java_lang_reflect_AbstractMethod.get(), Abstract_method_class);
+
+  // Method extends AbstractMethod so must reset after.
+  java_lang_reflect_Method->SetStatus(Class::kStatusNotReady);
+  Class* Method_class = FindSystemClass("Ljava/lang/reflect/Method;");
+  CHECK_EQ(java_lang_reflect_Method.get(), Method_class);
+
+  // Constructor extends AbstractMethod so must reset after.
   java_lang_reflect_Constructor->SetStatus(Class::kStatusNotReady);
   Class* Constructor_class = FindSystemClass("Ljava/lang/reflect/Constructor;");
   CHECK_EQ(java_lang_reflect_Constructor.get(), Constructor_class);
@@ -402,9 +450,15 @@
   Class* Field_class = FindSystemClass("Ljava/lang/reflect/Field;");
   CHECK_EQ(java_lang_reflect_Field.get(), Field_class);
 
-  java_lang_reflect_Method->SetStatus(Class::kStatusNotReady);
-  Class* Method_class = FindSystemClass("Ljava/lang/reflect/Method;");
-  CHECK_EQ(java_lang_reflect_Method.get(), Method_class);
+  Class* String_array_class = FindSystemClass(class_roots_descriptors_[kJavaLangStringArrayClass]);
+  CHECK_EQ(object_array_string.get(), String_array_class);
+
+  Class* Field_array_class = FindSystemClass(class_roots_descriptors_[kJavaLangReflectFieldArrayClass]);
+  CHECK_EQ(object_array_field.get(), Field_array_class);
+
+  Class* Abstract_method_array_class =
+      FindSystemClass(class_roots_descriptors_[kJavaLangReflectAbstractMethodArrayClass]);
+  CHECK_EQ(object_array_abstract_method.get(), Abstract_method_array_class);
 
   // End of special init trickery, subsequent classes may be loaded via FindSystemClass
 
@@ -935,7 +989,8 @@
   DCHECK(array_iftable_ == GetClassRoot(kBooleanArrayClass)->GetIfTable());
   // String class root was set above
   Field::SetClass(GetClassRoot(kJavaLangReflectField));
-  Method::SetClasses(GetClassRoot(kJavaLangReflectConstructor), GetClassRoot(kJavaLangReflectMethod));
+  AbstractMethod::SetClasses(GetClassRoot(kJavaLangReflectConstructor),
+                             GetClassRoot(kJavaLangReflectMethod));
   BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass));
   ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass));
   CharArray::SetArrayClass(GetClassRoot(kCharArrayClass));
@@ -1034,7 +1089,7 @@
 ClassLinker::~ClassLinker() {
   String::ResetClass();
   Field::ResetClass();
-  Method::ResetClasses();
+  AbstractMethod::ResetClasses();
   BooleanArray::ResetArrayClass();
   ByteArray::ResetArrayClass();
   CharArray::ResetArrayClass();
@@ -1050,7 +1105,10 @@
 }
 
 DexCache* ClassLinker::AllocDexCache(const DexFile& dex_file) {
-  SirtRef<DexCache> dex_cache(down_cast<DexCache*>(AllocObjectArray<Object>(DexCache::LengthAsArray())));
+  Heap* heap = Runtime::Current()->GetHeap();
+  Class* dex_cache_class = GetClassRoot(kJavaLangDexCache);
+  SirtRef<DexCache> dex_cache(
+      down_cast<DexCache*>(heap->AllocObject(dex_cache_class, dex_cache_class->GetObjectSize())));
   if (dex_cache.get() == NULL) {
     return NULL;
   }
@@ -1058,7 +1116,7 @@
   if (location.get() == NULL) {
     return NULL;
   }
-  SirtRef<ObjectArray<String> > strings(AllocObjectArray<String>(dex_file.NumStringIds()));
+  SirtRef<ObjectArray<String> > strings(AllocStringArray(dex_file.NumStringIds()));
   if (strings.get() == NULL) {
     return NULL;
   }
@@ -1066,11 +1124,11 @@
   if (types.get() == NULL) {
     return NULL;
   }
-  SirtRef<ObjectArray<Method> > methods(AllocObjectArray<Method>(dex_file.NumMethodIds()));
+  SirtRef<ObjectArray<AbstractMethod> > methods(AllocMethodArray(dex_file.NumMethodIds()));
   if (methods.get() == NULL) {
     return NULL;
   }
-  SirtRef<ObjectArray<Field> > fields(AllocObjectArray<Field>(dex_file.NumFieldIds()));
+  SirtRef<ObjectArray<Field> > fields(AllocFieldArray(dex_file.NumFieldIds()));
   if (fields.get() == NULL) {
     return NULL;
   }
@@ -1079,7 +1137,8 @@
     return NULL;
   }
 
-  dex_cache->Init(location.get(),
+  dex_cache->Init(&dex_file,
+                  location.get(),
                   strings.get(),
                   types.get(),
                   methods.get(),
@@ -1117,6 +1176,10 @@
   return down_cast<Method*>(GetClassRoot(kJavaLangReflectMethod)->AllocObject());
 }
 
+Constructor* ClassLinker::AllocConstructor() {
+  return down_cast<Constructor*>(GetClassRoot(kJavaLangReflectConstructor)->AllocObject());
+}
+
 ObjectArray<StackTraceElement>* ClassLinker::AllocStackTraceElementArray(size_t length) {
   return ObjectArray<StackTraceElement>::Alloc(
       GetClassRoot(kJavaLangStackTraceElementArrayClass),
@@ -1255,10 +1318,14 @@
       klass.reset(GetClassRoot(kJavaLangClass));
     } else if (descriptor == "Ljava/lang/String;") {
       klass.reset(GetClassRoot(kJavaLangString));
-    } else if (descriptor == "Ljava/lang/reflect/Constructor;") {
-      klass.reset(GetClassRoot(kJavaLangReflectConstructor));
+    } else if (descriptor == "Ljava/lang/DexCache;") {
+      klass.reset(GetClassRoot(kJavaLangDexCache));
     } else if (descriptor == "Ljava/lang/reflect/Field;") {
       klass.reset(GetClassRoot(kJavaLangReflectField));
+    } else if (descriptor == "Ljava/lang/reflect/AbstractMethod;") {
+      klass.reset(GetClassRoot(kJavaLangReflectAbstractMethod));
+    } else if (descriptor == "Ljava/lang/reflect/Constructor;") {
+      klass.reset(GetClassRoot(kJavaLangReflectConstructor));
     } else if (descriptor == "Ljava/lang/reflect/Method;") {
       klass.reset(GetClassRoot(kJavaLangReflectMethod));
     } else {
@@ -1373,7 +1440,7 @@
   return oat_class;
 }
 
-const OatFile::OatMethod ClassLinker::GetOatMethodFor(const Method* method) {
+const OatFile::OatMethod ClassLinker::GetOatMethodFor(const AbstractMethod* method) {
   // Although we overwrite the trampoline of non-static methods, we may get here via the resolution
   // method for direct methods (or virtual methods made direct).
   Class* declaring_class = method->GetDeclaringClass();
@@ -1403,7 +1470,7 @@
 }
 
 // Special case to get oat code without overwriting a trampoline.
-const void* ClassLinker::GetOatCodeFor(const Method* method) {
+const void* ClassLinker::GetOatCodeFor(const AbstractMethod* method) {
   CHECK(Runtime::Current()->IsCompiler() || method->GetDeclaringClass()->IsInitializing());
   return GetOatMethodFor(method).GetCode();
 }
@@ -1435,7 +1502,7 @@
   // Link the code of methods skipped by LinkCode
   const void* trampoline = Runtime::Current()->GetResolutionStubArray(Runtime::kStaticMethod)->GetData();
   for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) {
-    Method* method = klass->GetDirectMethod(i);
+    AbstractMethod* method = klass->GetDirectMethod(i);
     if (Runtime::Current()->IsMethodTracingActive()) {
       Trace* tracer = Runtime::Current()->GetTracer();
       if (tracer->GetSavedCodeFromMap(method) == trampoline) {
@@ -1454,7 +1521,7 @@
   }
 }
 
-static void LinkCode(SirtRef<Method>& method, const OatFile::OatClass* oat_class,
+static void LinkCode(SirtRef<AbstractMethod>& method, const OatFile::OatClass* oat_class,
                      uint32_t method_index)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   // Every kind of method should at least get an invoke stub from the oat_method.
@@ -1535,17 +1602,16 @@
   // Load methods.
   if (it.NumDirectMethods() != 0) {
     // TODO: append direct methods to class object
-    klass->SetDirectMethods(AllocObjectArray<Method>(it.NumDirectMethods()));
+    klass->SetDirectMethods(AllocObjectArray<AbstractMethod>(it.NumDirectMethods()));
   }
   if (it.NumVirtualMethods() != 0) {
     // TODO: append direct methods to class object
-    klass->SetVirtualMethods(AllocObjectArray<Method>(it.NumVirtualMethods()));
+    klass->SetVirtualMethods(AllocObjectArray<AbstractMethod>(it.NumVirtualMethods()));
   }
   size_t class_def_method_index = 0;
   for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) {
-    SirtRef<Method> method(AllocMethod());
+    SirtRef<AbstractMethod> method(LoadMethod(dex_file, it, klass));
     klass->SetDirectMethod(i, method.get());
-    LoadMethod(dex_file, it, klass, method);
     if (oat_class.get() != NULL) {
       LinkCode(method, oat_class.get(), class_def_method_index);
     }
@@ -1553,9 +1619,8 @@
     class_def_method_index++;
   }
   for (size_t i = 0; it.HasNextVirtualMethod(); i++, it.Next()) {
-    SirtRef<Method> method(AllocMethod());
+    SirtRef<AbstractMethod> method(LoadMethod(dex_file, it, klass));
     klass->SetVirtualMethod(i, method.get());
-    LoadMethod(dex_file, it, klass, method);
     DCHECK_EQ(class_def_method_index, it.NumDirectMethods() + i);
     if (oat_class.get() != NULL) {
       LinkCode(method, oat_class.get(), class_def_method_index);
@@ -1573,18 +1638,23 @@
   dst->SetAccessFlags(it.GetMemberAccessFlags());
 }
 
-void ClassLinker::LoadMethod(const DexFile& dex_file, const ClassDataItemIterator& it,
-                             SirtRef<Class>& klass, SirtRef<Method>& dst) {
+AbstractMethod* ClassLinker::LoadMethod(const DexFile& dex_file, const ClassDataItemIterator& it,
+                             SirtRef<Class>& klass) {
   uint32_t dex_method_idx = it.GetMemberIndex();
-  dst->SetDexMethodIndex(dex_method_idx);
   const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx);
-  dst->SetDeclaringClass(klass.get());
-
-
   StringPiece method_name(dex_file.GetMethodName(method_id));
+
+  AbstractMethod* dst = NULL;
   if (method_name == "<init>") {
-    dst->SetClass(GetClassRoot(kJavaLangReflectConstructor));
+    dst = AllocConstructor();
+  } else {
+    dst = AllocMethod();
   }
+  DCHECK(dst->IsMethod()) << PrettyDescriptor(dst->GetClass());
+
+  const char* old_cause = Thread::Current()->StartAssertNoThreadSuspension("LoadMethod");
+  dst->SetDexMethodIndex(dex_method_idx);
+  dst->SetDeclaringClass(klass.get());
 
   if (method_name == "finalize") {
     // Create the prototype for a signature of "()V"
@@ -1623,6 +1693,11 @@
   dst->SetDexCacheResolvedMethods(klass->GetDexCache()->GetResolvedMethods());
   dst->SetDexCacheResolvedTypes(klass->GetDexCache()->GetResolvedTypes());
   dst->SetDexCacheInitializedStaticStorage(klass->GetDexCache()->GetInitializedStaticStorage());
+
+  CHECK(dst->IsMethod());
+
+  Thread::Current()->EndAssertNoThreadSuspension(old_cause);
+  return dst;
 }
 
 void ClassLinker::AppendToBootClassPath(const DexFile& dex_file) {
@@ -1638,8 +1713,8 @@
 
 bool ClassLinker::IsDexFileRegisteredLocked(const DexFile& dex_file) const {
   dex_lock_.AssertHeld();
-  for (size_t i = 0; i != dex_files_.size(); ++i) {
-    if (dex_files_[i] == &dex_file) {
+  for (size_t i = 0; i != dex_caches_.size(); ++i) {
+    if (dex_caches_[i]->GetDexFile() == &dex_file) {
       return true;
     }
   }
@@ -1655,8 +1730,8 @@
   dex_lock_.AssertHeld();
   CHECK(dex_cache.get() != NULL) << dex_file.GetLocation();
   CHECK(dex_cache->GetLocation()->Equals(dex_file.GetLocation()));
-  dex_files_.push_back(&dex_file);
   dex_caches_.push_back(dex_cache.get());
+  dex_cache->SetDexFile(&dex_file);
 }
 
 void ClassLinker::RegisterDexFile(const DexFile& dex_file) {
@@ -1684,30 +1759,29 @@
   RegisterDexFileLocked(dex_file, dex_cache);
 }
 
+// TODO: Remove.
 const DexFile& ClassLinker::FindDexFile(const DexCache* dex_cache) const {
   CHECK(dex_cache != NULL);
-  MutexLock mu(dex_lock_);
-  for (size_t i = 0; i != dex_caches_.size(); ++i) {
-    if (dex_caches_[i] == dex_cache) {
-      return *dex_files_[i];
-    }
+  const DexFile* dex_file = dex_cache->GetDexFile();
+  if (dex_file == NULL) {
+    LOG(FATAL) << "DexCache has no DexFile " << dex_cache->GetLocation()->ToModifiedUtf8();
   }
-  LOG(FATAL) << "Failed to find DexFile for DexCache " << dex_cache->GetLocation()->ToModifiedUtf8();
-  return *dex_files_[-1];
+  return *dex_file;
 }
 
 DexCache* ClassLinker::FindDexCache(const DexFile& dex_file) const {
   MutexLock mu(dex_lock_);
-  for (size_t i = 0; i != dex_files_.size(); ++i) {
-    if (dex_files_[i] == &dex_file) {
-      return dex_caches_[i];
+  for (size_t i = 0; i != dex_caches_.size(); ++i) {
+    DexCache* dex_cache = dex_caches_[i];
+    if (dex_cache->GetDexFile() == &dex_file) {
+      return dex_cache;
     }
   }
   LOG(FATAL) << "Failed to find DexCache for DexFile " << dex_file.GetLocation();
   return NULL;
 }
 
-void ClassLinker::FixupDexCaches(Method* resolution_method) const {
+void ClassLinker::FixupDexCaches(AbstractMethod* resolution_method) const {
   MutexLock mu(dex_lock_);
   for (size_t i = 0; i != dex_caches_.size(); ++i) {
     dex_caches_[i]->Fixup(resolution_method);
@@ -1788,6 +1862,12 @@
       new_class.reset(GetClassRoot(kClassArrayClass));
     } else if (descriptor == "[Ljava/lang/Object;") {
       new_class.reset(GetClassRoot(kObjectArrayClass));
+    } else if (descriptor == class_roots_descriptors_[kJavaLangStringArrayClass]) {
+      new_class.reset(GetClassRoot(kJavaLangStringArrayClass));
+    } else if (descriptor == class_roots_descriptors_[kJavaLangReflectFieldArrayClass]) {
+      new_class.reset(GetClassRoot(kJavaLangReflectFieldArrayClass));
+    } else if (descriptor == class_roots_descriptors_[kJavaLangReflectAbstractMethodArrayClass]) {
+      new_class.reset(GetClassRoot(kJavaLangReflectAbstractMethodArrayClass));
     } else if (descriptor == "[C") {
       new_class.reset(GetClassRoot(kCharArrayClass));
     } else if (descriptor == "[I") {
@@ -2164,7 +2244,7 @@
   }
 }
 
-void ClassLinker::ResolveMethodExceptionHandlerTypes(const DexFile& dex_file, Method* method) {
+void ClassLinker::ResolveMethodExceptionHandlerTypes(const DexFile& dex_file, AbstractMethod* method) {
   // similar to DexVerifier::ScanTryCatchBlocks and dex2oat's ResolveExceptionsForMethod.
   const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->GetCodeItemOffset());
   if (code_item == NULL) {
@@ -2193,11 +2273,11 @@
   }
 }
 
-static void CheckProxyConstructor(Method* constructor);
-static void CheckProxyMethod(Method* method, SirtRef<Method>& prototype);
+static void CheckProxyConstructor(AbstractMethod* constructor);
+static void CheckProxyMethod(AbstractMethod* method, SirtRef<AbstractMethod>& prototype);
 
 Class* ClassLinker::CreateProxyClass(String* name, ObjectArray<Class>* interfaces,
-                                     ClassLoader* loader, ObjectArray<Method>* methods,
+                                     ClassLoader* loader, ObjectArray<AbstractMethod>* methods,
                                      ObjectArray<ObjectArray<Class> >* throws) {
   SirtRef<Class> klass(AllocClass(GetClassRoot(kJavaLangClass), sizeof(SynthesizedProxyClass)));
   CHECK(klass.get() != NULL);
@@ -2231,14 +2311,14 @@
   throws_sfield->SetAccessFlags(kAccStatic | kAccPublic | kAccFinal);
 
   // Proxies have 1 direct method, the constructor
-  klass->SetDirectMethods(AllocObjectArray<Method>(1));
+  klass->SetDirectMethods(AllocObjectArray<AbstractMethod>(1));
   klass->SetDirectMethod(0, CreateProxyConstructor(klass, proxy_class));
 
   // Create virtual method using specified prototypes
   size_t num_virtual_methods = methods->GetLength();
-  klass->SetVirtualMethods(AllocObjectArray<Method>(num_virtual_methods));
+  klass->SetVirtualMethods(AllocObjectArray<AbstractMethod>(num_virtual_methods));
   for (size_t i = 0; i < num_virtual_methods; ++i) {
-    SirtRef<Method> prototype(methods->Get(i));
+    SirtRef<AbstractMethod> prototype(methods->Get(i));
     klass->SetVirtualMethod(i, CreateProxyMethod(klass, prototype));
   }
 
@@ -2263,7 +2343,7 @@
     CHECK(klass->GetIFields() == NULL);
     CheckProxyConstructor(klass->GetDirectMethod(0));
     for (size_t i = 0; i < num_virtual_methods; ++i) {
-      SirtRef<Method> prototype(methods->Get(i));
+      SirtRef<AbstractMethod> prototype(methods->Get(i));
       CheckProxyMethod(klass->GetVirtualMethod(i), prototype);
     }
 
@@ -2289,7 +2369,7 @@
   return DotToDescriptor(name->ToModifiedUtf8().c_str());
 }
 
-Method* ClassLinker::FindMethodForProxy(const Class* proxy_class, const Method* proxy_method) {
+AbstractMethod* ClassLinker::FindMethodForProxy(const Class* proxy_class, const AbstractMethod* proxy_method) {
   DCHECK(proxy_class->IsProxyClass());
   DCHECK(proxy_method->IsProxyMethod());
   // Locate the dex cache of the original interface/Object
@@ -2306,27 +2386,27 @@
   }
   CHECK(dex_cache != NULL);
   uint32_t method_idx = proxy_method->GetDexMethodIndex();
-  Method* resolved_method = dex_cache->GetResolvedMethod(method_idx);
+  AbstractMethod* resolved_method = dex_cache->GetResolvedMethod(method_idx);
   CHECK(resolved_method != NULL);
   return resolved_method;
 }
 
 
-Method* ClassLinker::CreateProxyConstructor(SirtRef<Class>& klass, Class* proxy_class) {
+AbstractMethod* ClassLinker::CreateProxyConstructor(SirtRef<Class>& klass, Class* proxy_class) {
   // Create constructor for Proxy that must initialize h
-  ObjectArray<Method>* proxy_direct_methods = proxy_class->GetDirectMethods();
+  ObjectArray<AbstractMethod>* proxy_direct_methods = proxy_class->GetDirectMethods();
   CHECK_EQ(proxy_direct_methods->GetLength(), 15);
-  Method* proxy_constructor = proxy_direct_methods->Get(2);
+  AbstractMethod* proxy_constructor = proxy_direct_methods->Get(2);
   // Clone the existing constructor of Proxy (our constructor would just invoke it so steal its
   // code_ too)
-  Method* constructor = down_cast<Method*>(proxy_constructor->Clone());
+  AbstractMethod* constructor = down_cast<AbstractMethod*>(proxy_constructor->Clone());
   // Make this constructor public and fix the class to be our Proxy version
   constructor->SetAccessFlags((constructor->GetAccessFlags() & ~kAccProtected) | kAccPublic);
   constructor->SetDeclaringClass(klass.get());
   return constructor;
 }
 
-static void CheckProxyConstructor(Method* constructor)
+static void CheckProxyConstructor(AbstractMethod* constructor)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   CHECK(constructor->IsConstructor());
   MethodHelper mh(constructor);
@@ -2335,14 +2415,14 @@
   DCHECK(constructor->IsPublic());
 }
 
-Method* ClassLinker::CreateProxyMethod(SirtRef<Class>& klass, SirtRef<Method>& prototype) {
+AbstractMethod* ClassLinker::CreateProxyMethod(SirtRef<Class>& klass, SirtRef<AbstractMethod>& 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());
   // We steal everything from the prototype (such as DexCache, invoke stub, etc.) then specialize
   // as necessary
-  Method* method = down_cast<Method*>(prototype->Clone());
+  AbstractMethod* method = down_cast<AbstractMethod*>(prototype->Clone());
 
   // Set class to be the concrete proxy class and clear the abstract flag, modify exceptions to
   // the intersection of throw exceptions as defined in Proxy
@@ -2351,7 +2431,7 @@
 
   // At runtime the method looks like a reference and argument saving method, clone the code
   // related parameters from this method.
-  Method* refs_and_args = Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs);
+  AbstractMethod* refs_and_args = Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs);
   method->SetCoreSpillMask(refs_and_args->GetCoreSpillMask());
   method->SetFpSpillMask(refs_and_args->GetFpSpillMask());
   method->SetFrameSizeInBytes(refs_and_args->GetFrameSizeInBytes());
@@ -2365,7 +2445,7 @@
   return method;
 }
 
-static void CheckProxyMethod(Method* method, SirtRef<Method>& prototype)
+static void CheckProxyMethod(AbstractMethod* method, SirtRef<AbstractMethod>& prototype)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   // Basic sanity
   CHECK(!prototype->IsFinal());
@@ -2395,7 +2475,7 @@
 
   Thread* self = Thread::Current();
 
-  Method* clinit = NULL;
+  AbstractMethod* clinit = NULL;
   {
     // see JLS 3rd edition, 12.4.2 "Detailed Initialization Procedure" for the locking protocol
     ObjectLock lock(klass);
@@ -2555,7 +2635,7 @@
       klass->GetClassLoader() != klass->GetSuperClass()->GetClassLoader()) {
     const Class* super = klass->GetSuperClass();
     for (int i = super->GetVTable()->GetLength() - 1; i >= 0; --i) {
-      const Method* method = klass->GetVTable()->Get(i);
+      const AbstractMethod* method = klass->GetVTable()->Get(i);
       if (method != super->GetVTable()->Get(i) &&
           !IsSameMethodSignatureInDifferentClassContexts(method, super, klass)) {
         ThrowLinkageError("Class %s method %s resolves differently in superclass %s",
@@ -2570,7 +2650,7 @@
     Class* interface = interface_entry->GetInterface();
     if (klass->GetClassLoader() != interface->GetClassLoader()) {
       for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
-        const Method* method = interface_entry->GetMethodArray()->Get(j);
+        const AbstractMethod* method = interface_entry->GetMethodArray()->Get(j);
         if (!IsSameMethodSignatureInDifferentClassContexts(method, interface,
                                                            method->GetDeclaringClass())) {
           ThrowLinkageError("Class %s method %s resolves differently in interface %s",
@@ -2587,7 +2667,7 @@
 
 // Returns true if classes referenced by the signature of the method are the
 // same classes in klass1 as they are in klass2.
-bool ClassLinker::IsSameMethodSignatureInDifferentClassContexts(const Method* method,
+bool ClassLinker::IsSameMethodSignatureInDifferentClassContexts(const AbstractMethod* method,
                                                                 const Class* klass1,
                                                                 const Class* klass2) {
   if (klass1 == klass2) {
@@ -2872,16 +2952,16 @@
     size_t actual_count = klass->GetSuperClass()->GetVTable()->GetLength();
     CHECK_LE(actual_count, max_count);
     // TODO: do not assign to the vtable field until it is fully constructed.
-    SirtRef<ObjectArray<Method> > vtable(klass->GetSuperClass()->GetVTable()->CopyOf(max_count));
+    SirtRef<ObjectArray<AbstractMethod> > vtable(klass->GetSuperClass()->GetVTable()->CopyOf(max_count));
     // See if any of our virtual methods override the superclass.
     MethodHelper local_mh(NULL, this);
     MethodHelper super_mh(NULL, this);
     for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
-      Method* local_method = klass->GetVirtualMethodDuringLinking(i);
+      AbstractMethod* local_method = klass->GetVirtualMethodDuringLinking(i);
       local_mh.ChangeMethod(local_method);
       size_t j = 0;
       for (; j < actual_count; ++j) {
-        Method* super_method = vtable->Get(j);
+        AbstractMethod* super_method = vtable->Get(j);
         super_mh.ChangeMethod(super_method);
         if (local_mh.HasSameNameAndSignature(&super_mh)) {
           if (klass->CanAccessMember(super_method->GetDeclaringClass(), super_method->GetAccessFlags())) {
@@ -2925,9 +3005,9 @@
       ThrowClassFormatError("Too many methods: %d", num_virtual_methods);
       return false;
     }
-    SirtRef<ObjectArray<Method> > vtable(AllocObjectArray<Method>(num_virtual_methods));
+    SirtRef<ObjectArray<AbstractMethod> > vtable(AllocObjectArray<AbstractMethod>(num_virtual_methods));
     for (size_t i = 0; i < num_virtual_methods; ++i) {
-      Method* virtual_method = klass->GetVirtualMethodDuringLinking(i);
+      AbstractMethod* virtual_method = klass->GetVirtualMethodDuringLinking(i);
       vtable->Set(i, virtual_method);
       virtual_method->SetMethodIndex(i & 0xFFFF);
     }
@@ -3021,17 +3101,17 @@
   if (klass->IsInterface() /*|| super_ifcount == ifcount*/) {
     return true;
   }
-  std::vector<Method*> miranda_list;
+  std::vector<AbstractMethod*> miranda_list;
   MethodHelper vtable_mh(NULL, this);
   MethodHelper interface_mh(NULL, this);
   for (size_t i = 0; i < ifcount; ++i) {
     InterfaceEntry* interface_entry = iftable->Get(i);
     Class* interface = interface_entry->GetInterface();
-    ObjectArray<Method>* method_array = AllocObjectArray<Method>(interface->NumVirtualMethods());
+    ObjectArray<AbstractMethod>* method_array = AllocObjectArray<AbstractMethod>(interface->NumVirtualMethods());
     interface_entry->SetMethodArray(method_array);
-    ObjectArray<Method>* vtable = klass->GetVTableDuringLinking();
+    ObjectArray<AbstractMethod>* vtable = klass->GetVTableDuringLinking();
     for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
-      Method* interface_method = interface->GetVirtualMethod(j);
+      AbstractMethod* interface_method = interface->GetVirtualMethod(j);
       interface_mh.ChangeMethod(interface_method);
       int32_t k;
       // For each method listed in the interface's method list, find the
@@ -3043,7 +3123,7 @@
       // those don't end up in the virtual method table, so it shouldn't
       // matter which direction we go.  We walk it backward anyway.)
       for (k = vtable->GetLength() - 1; k >= 0; --k) {
-        Method* vtable_method = vtable->Get(k);
+        AbstractMethod* vtable_method = vtable->Get(k);
         vtable_mh.ChangeMethod(vtable_method);
         if (interface_mh.HasSameNameAndSignature(&vtable_mh)) {
           if (!vtable_method->IsPublic()) {
@@ -3056,9 +3136,9 @@
         }
       }
       if (k < 0) {
-        SirtRef<Method> miranda_method(NULL);
+        SirtRef<AbstractMethod> miranda_method(NULL);
         for (size_t mir = 0; mir < miranda_list.size(); mir++) {
-          Method* mir_method = miranda_list[mir];
+          AbstractMethod* mir_method = miranda_list[mir];
           vtable_mh.ChangeMethod(mir_method);
           if (interface_mh.HasSameNameAndSignature(&vtable_mh)) {
             miranda_method.reset(miranda_list[mir]);
@@ -3067,7 +3147,7 @@
         }
         if (miranda_method.get() == NULL) {
           // point the interface table at a phantom slot
-          miranda_method.reset(down_cast<Method*>(interface_method->Clone()));
+          miranda_method.reset(down_cast<AbstractMethod*>(interface_method->Clone()));
           miranda_list.push_back(miranda_method.get());
         }
         method_array->Set(j, miranda_method.get());
@@ -3078,16 +3158,16 @@
     int old_method_count = klass->NumVirtualMethods();
     int new_method_count = old_method_count + miranda_list.size();
     klass->SetVirtualMethods((old_method_count == 0)
-                             ? AllocObjectArray<Method>(new_method_count)
+                             ? AllocObjectArray<AbstractMethod>(new_method_count)
                              : klass->GetVirtualMethods()->CopyOf(new_method_count));
 
-    SirtRef<ObjectArray<Method> > vtable(klass->GetVTableDuringLinking());
+    SirtRef<ObjectArray<AbstractMethod> > vtable(klass->GetVTableDuringLinking());
     CHECK(vtable.get() != NULL);
     int old_vtable_count = vtable->GetLength();
     int new_vtable_count = old_vtable_count + miranda_list.size();
     vtable.reset(vtable->CopyOf(new_vtable_count));
     for (size_t i = 0; i < miranda_list.size(); ++i) {
-      Method* method = miranda_list[i];
+      AbstractMethod* method = miranda_list[i];
       // Leave the declaring class alone as type indices are relative to it
       method->SetAccessFlags(method->GetAccessFlags() | kAccMiranda);
       method->SetMethodIndex(0xFFFF & (old_vtable_count + i));
@@ -3098,7 +3178,7 @@
     klass->SetVTable(vtable.get());
   }
 
-  ObjectArray<Method>* vtable = klass->GetVTableDuringLinking();
+  ObjectArray<AbstractMethod>* vtable = klass->GetVTableDuringLinking();
   for (int i = 0; i < vtable->GetLength(); ++i) {
     CHECK(vtable->Get(i) != NULL);
   }
@@ -3396,15 +3476,15 @@
   return resolved;
 }
 
-Method* ClassLinker::ResolveMethod(const DexFile& dex_file,
+AbstractMethod* ClassLinker::ResolveMethod(const DexFile& dex_file,
                                    uint32_t method_idx,
                                    DexCache* dex_cache,
                                    ClassLoader* class_loader,
-                                   const Method* referrer,
+                                   const AbstractMethod* referrer,
                                    InvokeType type) {
   DCHECK(dex_cache != NULL);
   // Check for hit in the dex cache.
-  Method* resolved = dex_cache->GetResolvedMethod(method_idx);
+  AbstractMethod* resolved = dex_cache->GetResolvedMethod(method_idx);
   if (resolved != NULL) {
     return resolved;
   }
@@ -3608,7 +3688,7 @@
   return resolved;
 }
 
-const char* ClassLinker::MethodShorty(uint32_t method_idx, Method* referrer, uint32_t* length) {
+const char* ClassLinker::MethodShorty(uint32_t method_idx, AbstractMethod* referrer, uint32_t* length) {
   Class* declaring_class = referrer->GetDeclaringClass();
   DexCache* dex_cache = declaring_class->GetDexCache();
   const DexFile& dex_file = FindDexFile(dex_cache);
diff --git a/src/class_linker.h b/src/class_linker.h
index 3cee7f0..67c2fbe 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -98,7 +98,7 @@
   // Resolve a String with the given index from the DexFile, storing the
   // result in the DexCache. The referrer is used to identify the
   // target DexCache and ClassLoader to use for resolution.
-  String* ResolveString(uint32_t string_idx, const Method* referrer)
+  String* ResolveString(uint32_t string_idx, const AbstractMethod* referrer)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     String* resolved_string = referrer->GetDexCacheStrings()->Get(string_idx);
     if (UNLIKELY(resolved_string == NULL)) {
@@ -129,7 +129,7 @@
   // Resolve a Type with the given index from the DexFile, storing the
   // result in the DexCache. The referrer is used to identify the
   // target DexCache and ClassLoader to use for resolution.
-  Class* ResolveType(uint16_t type_idx, const Method* referrer)
+  Class* ResolveType(uint16_t type_idx, const AbstractMethod* referrer)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     Class* resolved_type = referrer->GetDexCacheResolvedTypes()->Get(type_idx);
     if (UNLIKELY(resolved_type == NULL)) {
@@ -170,17 +170,17 @@
   // in ResolveType. What is unique is the method type argument which
   // is used to determine if this method is a direct, static, or
   // virtual method.
-  Method* ResolveMethod(const DexFile& dex_file,
+  AbstractMethod* ResolveMethod(const DexFile& dex_file,
                         uint32_t method_idx,
                         DexCache* dex_cache,
                         ClassLoader* class_loader,
-                        const Method* referrer,
+                        const AbstractMethod* referrer,
                         InvokeType type)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  Method* ResolveMethod(uint32_t method_idx, const Method* referrer, InvokeType type)
+  AbstractMethod* ResolveMethod(uint32_t method_idx, const AbstractMethod* referrer, InvokeType type)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    Method* resolved_method = referrer->GetDexCacheResolvedMethods()->Get(method_idx);
+    AbstractMethod* resolved_method = referrer->GetDexCacheResolvedMethods()->Get(method_idx);
     if (UNLIKELY(resolved_method == NULL || resolved_method->IsRuntimeMethod())) {
       Class* declaring_class = referrer->GetDeclaringClass();
       DexCache* dex_cache = declaring_class->GetDexCache();
@@ -191,7 +191,7 @@
     return resolved_method;
   }
 
-  Field* ResolveField(uint32_t field_idx, const Method* referrer, bool is_static)
+  Field* ResolveField(uint32_t field_idx, const AbstractMethod* referrer, bool is_static)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     Field* resolved_field =
         referrer->GetDeclaringClass()->GetDexCache()->GetResolvedField(field_idx);
@@ -228,7 +228,7 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Get shorty from method index without resolution. Used to do handlerization.
-  const char* MethodShorty(uint32_t method_idx, Method* referrer, uint32_t* length)
+  const char* MethodShorty(uint32_t method_idx, AbstractMethod* referrer, uint32_t* length)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Returns true on success, false if there's an exception pending.
@@ -273,7 +273,7 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   bool IsDexFileRegistered(const DexFile& dex_file) const
       LOCKS_EXCLUDED(dex_lock_);
-  void FixupDexCaches(Method* resolution_method) const
+  void FixupDexCaches(AbstractMethod* resolution_method) const
       LOCKS_EXCLUDED(dex_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -323,6 +323,22 @@
     return ObjectArray<Class>::Alloc(GetClassRoot(kClassArrayClass), length);
   }
 
+  ObjectArray<String>* AllocStringArray(size_t length)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return ObjectArray<String>::Alloc(GetClassRoot(kJavaLangStringArrayClass), length);
+  }
+
+  ObjectArray<AbstractMethod>* AllocMethodArray(size_t length)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return ObjectArray<AbstractMethod>::Alloc(
+        GetClassRoot(kJavaLangReflectAbstractMethodArrayClass), length);
+  }
+
+  ObjectArray<Field>* AllocFieldArray(size_t length)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return ObjectArray<Field>::Alloc(GetClassRoot(kJavaLangReflectFieldArrayClass), length);
+  }
+
   ObjectArray<StackTraceElement>* AllocStackTraceElementArray(size_t length)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -332,20 +348,20 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void ResolveClassExceptionHandlerTypes(const DexFile& dex_file, Class* klass)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  void ResolveMethodExceptionHandlerTypes(const DexFile& dex_file, Method* klass)
+  void ResolveMethodExceptionHandlerTypes(const DexFile& dex_file, AbstractMethod* klass)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   Class* CreateProxyClass(String* name, ObjectArray<Class>* interfaces, ClassLoader* loader,
-                          ObjectArray<Method>* methods, ObjectArray<ObjectArray<Class> >* throws)
+                          ObjectArray<AbstractMethod>* methods, ObjectArray<ObjectArray<Class> >* throws)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   std::string GetDescriptorForProxy(const Class* proxy_class)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  Method* FindMethodForProxy(const Class* proxy_class, const Method* proxy_method)
+  AbstractMethod* FindMethodForProxy(const Class* proxy_class, const AbstractMethod* proxy_method)
       LOCKS_EXCLUDED(dex_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Get the oat code for a method when its class isn't yet initialized
-  const void* GetOatCodeFor(const Method* method)
+  const void* GetOatCodeFor(const AbstractMethod* method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Relocate the OatFiles (ELF images)
@@ -357,7 +373,7 @@
  private:
   explicit ClassLinker(InternTable*);
 
-  const OatFile::OatMethod GetOatMethodFor(const Method* method)
+  const OatFile::OatMethod GetOatMethodFor(const AbstractMethod* method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Initialize class linker by bootstraping from dex files
@@ -386,6 +402,7 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   Field* AllocField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   Method* AllocMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  Constructor* AllocConstructor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   InterfaceEntry* AllocInterfaceEntry(Class* interface)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -422,8 +439,8 @@
   void LoadField(const DexFile& dex_file, const ClassDataItemIterator& it, SirtRef<Class>& klass,
                  SirtRef<Field>& dst);
 
-  void LoadMethod(const DexFile& dex_file, const ClassDataItemIterator& dex_method,
-                  SirtRef<Class>& klass, SirtRef<Method>& dst)
+  AbstractMethod* LoadMethod(const DexFile& dex_file, const ClassDataItemIterator& dex_method,
+                  SirtRef<Class>& klass)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void FixupStaticTrampolines(Class* klass)
@@ -462,7 +479,7 @@
                                                 const Class* klass2)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  bool IsSameMethodSignatureInDifferentClassContexts(const Method* descriptor,
+  bool IsSameMethodSignatureInDifferentClassContexts(const AbstractMethod* descriptor,
                                                      const Class* klass1,
                                                      const Class* klass2)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -518,15 +535,14 @@
       EXCLUSIVE_LOCKS_REQUIRED(dex_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  Method* CreateProxyConstructor(SirtRef<Class>& klass, Class* proxy_class)
+  AbstractMethod* CreateProxyConstructor(SirtRef<Class>& klass, Class* proxy_class)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  Method* CreateProxyMethod(SirtRef<Class>& klass, SirtRef<Method>& prototype)
+  AbstractMethod* CreateProxyMethod(SirtRef<Class>& klass, SirtRef<AbstractMethod>& prototype)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   std::vector<const DexFile*> boot_class_path_;
 
   mutable Mutex dex_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
-  std::vector<const DexFile*> dex_files_ GUARDED_BY(dex_lock_);
   std::vector<DexCache*> dex_caches_ GUARDED_BY(dex_lock_);
   std::vector<const OatFile*> oat_files_ GUARDED_BY(dex_lock_);
 
@@ -551,11 +567,16 @@
     kClassArrayClass,
     kObjectArrayClass,
     kJavaLangString,
+    kJavaLangDexCache,
     kJavaLangRefReference,
     kJavaLangReflectConstructor,
     kJavaLangReflectField,
+    kJavaLangReflectAbstractMethod,
     kJavaLangReflectMethod,
     kJavaLangReflectProxy,
+    kJavaLangStringArrayClass,
+    kJavaLangReflectFieldArrayClass,
+    kJavaLangReflectAbstractMethodArrayClass,
     kJavaLangClassLoader,
     kJavaLangThrowable,
     kJavaLangClassNotFoundException,
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index a0b4f1c..106598e 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -135,7 +135,7 @@
     EXPECT_STREQ(kh.GetDescriptor(), "Ljava/io/Serializable;");
   }
 
-  void AssertMethod(Method* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  void AssertMethod(AbstractMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     MethodHelper mh(method);
     EXPECT_TRUE(method != NULL);
     EXPECT_TRUE(method->GetClass() != NULL);
@@ -232,14 +232,14 @@
     EXPECT_TRUE(klass->CanAccess(klass));
 
     for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
-      Method* method = klass->GetDirectMethod(i);
+      AbstractMethod* method = klass->GetDirectMethod(i);
       AssertMethod(method);
       EXPECT_TRUE(method->IsDirect());
       EXPECT_EQ(klass, method->GetDeclaringClass());
     }
 
     for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
-      Method* method = klass->GetVirtualMethod(i);
+      AbstractMethod* method = klass->GetVirtualMethod(i);
       AssertMethod(method);
       EXPECT_FALSE(method->IsDirect());
       EXPECT_TRUE(method->GetDeclaringClass()->IsAssignableFrom(klass));
@@ -325,7 +325,7 @@
     class_linker_->VisitRoots(TestRootVisitor, NULL);
     // Verify the dex cache has resolution methods in all resolved method slots
     DexCache* dex_cache = class_linker_->FindDexCache(*dex);
-    ObjectArray<Method>* resolved_methods = dex_cache->GetResolvedMethods();
+    ObjectArray<AbstractMethod>* resolved_methods = dex_cache->GetResolvedMethods();
     for (size_t i = 0; i < static_cast<size_t>(resolved_methods->GetLength()); i++) {
       EXPECT_TRUE(resolved_methods->Get(i) != NULL);
     }
@@ -452,36 +452,41 @@
   };
 };
 
-struct MethodOffsets : public CheckOffsets<Method> {
-  MethodOffsets() : CheckOffsets<Method>(false, "Ljava/lang/reflect/Method;") {
+struct AbstractMethodOffsets : public CheckOffsets<AbstractMethod> {
+  AbstractMethodOffsets() : CheckOffsets<AbstractMethod>(false, "Ljava/lang/reflect/AbstractMethod;") {
     // alphabetical references
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, declaring_class_),                      "declaringClass"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, dex_cache_initialized_static_storage_), "dexCacheInitializedStaticStorage"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, dex_cache_resolved_methods_),           "dexCacheResolvedMethods"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, dex_cache_resolved_types_),             "dexCacheResolvedTypes"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, dex_cache_strings_),                    "dexCacheStrings"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, declaring_class_),                      "declaringClass"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, dex_cache_initialized_static_storage_), "dexCacheInitializedStaticStorage"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, dex_cache_resolved_methods_),           "dexCacheResolvedMethods"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, dex_cache_resolved_types_),             "dexCacheResolvedTypes"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, dex_cache_strings_),                    "dexCacheStrings"));
 
     // alphabetical 32-bit
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, access_flags_),        "accessFlags"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, code_),                "code"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, code_item_offset_),    "codeItemOffset"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, core_spill_mask_),     "coreSpillMask"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, fp_spill_mask_),       "fpSpillMask"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, frame_size_in_bytes_), "frameSizeInBytes"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, native_gc_map_),       "gcMap"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, invoke_stub_),         "invokeStub"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, mapping_table_),       "mappingTable"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, method_dex_index_),    "methodDexIndex"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, method_index_),        "methodIndex"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, native_method_),       "nativeMethod"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, vmap_table_),          "vmapTable"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, access_flags_),        "accessFlags"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, code_),                "code"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, code_item_offset_),    "codeItemOffset"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, core_spill_mask_),     "coreSpillMask"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, fp_spill_mask_),       "fpSpillMask"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, frame_size_in_bytes_), "frameSizeInBytes"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, native_gc_map_),       "gcMap"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, invoke_stub_),         "invokeStub"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, mapping_table_),       "mappingTable"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, method_dex_index_),    "methodDexIndex"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, method_index_),        "methodIndex"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, native_method_),       "nativeMethod"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, vmap_table_),          "vmapTable"));
   };
 };
 
-struct ConstructorOffsets : public MethodOffsets {
-  ConstructorOffsets() : MethodOffsets() {
-    // We use Method* for both java.lang.reflect.Constructor and java.lang.reflect.Method.
-    class_descriptor = "Ljava/lang/reflect/Constructor;";
+struct ConstructorOffsets : public CheckOffsets<Constructor> {
+  // java.lang.reflect.Constructor is a subclass of java.lang.reflect.AbstractMethod
+  ConstructorOffsets() : CheckOffsets<Constructor>(false, "Ljava/lang/reflect/Constructor;") {
+  }
+};
+
+struct MethodOffsets : public CheckOffsets<Method> {
+  // java.lang.reflect.Method is a subclass of java.lang.reflect.AbstractMethod
+  MethodOffsets() : CheckOffsets<Method>(false, "Ljava/lang/reflect/Method;") {
   }
 };
 
@@ -604,6 +609,19 @@
   };
 };
 
+struct DexCacheOffsets : public CheckOffsets<DexCache> {
+  DexCacheOffsets() : CheckOffsets<DexCache>(false, "Ljava/lang/DexCache;") {
+    // alphabetical references
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(DexCache, initialized_static_storage_), "initializedStaticStorage"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(DexCache, location_),                   "location"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(DexCache, resolved_fields_),            "resolvedFields"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(DexCache, resolved_methods_),           "resolvedMethods"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(DexCache, resolved_types_),             "resolvedTypes"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(DexCache, strings_),                    "strings"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(DexCache, dex_file_),                   "dexFile"));
+  };
+};
+
 // C++ fields must exactly match the fields in the Java classes. If this fails,
 // reorder the fields in the C++ class. Managed class fields are ordered by
 // ClassLinker::LinkFields.
@@ -611,14 +629,16 @@
   ScopedObjectAccess soa(Thread::Current());
   EXPECT_TRUE(ObjectOffsets().Check());
   EXPECT_TRUE(ConstructorOffsets().Check());
-  EXPECT_TRUE(FieldOffsets().Check());
   EXPECT_TRUE(MethodOffsets().Check());
+  EXPECT_TRUE(FieldOffsets().Check());
+  EXPECT_TRUE(AbstractMethodOffsets().Check());
   EXPECT_TRUE(ClassOffsets().Check());
   EXPECT_TRUE(StringOffsets().Check());
   EXPECT_TRUE(ThrowableOffsets().Check());
   EXPECT_TRUE(StackTraceElementOffsets().Check());
   EXPECT_TRUE(ClassLoaderOffsets().Check());
   EXPECT_TRUE(ProxyOffsets().Check());
+  EXPECT_TRUE(DexCacheOffsets().Check());
 
   EXPECT_TRUE(ClassClassOffsets().Check());
   EXPECT_TRUE(StringClassOffsets().Check());
@@ -844,7 +864,7 @@
   // Static final primitives that are initialized by a compile-time constant
   // expression resolve to a copy of a constant value from the constant pool.
   // So <clinit> should be null.
-  Method* clinit = statics->FindDirectMethod("<clinit>", "()V");
+  AbstractMethod* clinit = statics->FindDirectMethod("<clinit>", "()V");
   EXPECT_TRUE(clinit == NULL);
 
   EXPECT_EQ(9U, statics->NumStaticFields());
@@ -931,15 +951,15 @@
   EXPECT_TRUE(K->IsAssignableFrom(B));
   EXPECT_TRUE(J->IsAssignableFrom(B));
 
-  Method* Ii = I->FindVirtualMethod("i", "()V");
-  Method* Jj1 = J->FindVirtualMethod("j1", "()V");
-  Method* Jj2 = J->FindVirtualMethod("j2", "()V");
-  Method* Kj1 = K->FindInterfaceMethod("j1", "()V");
-  Method* Kj2 = K->FindInterfaceMethod("j2", "()V");
-  Method* Kk = K->FindInterfaceMethod("k", "()V");
-  Method* Ai = A->FindVirtualMethod("i", "()V");
-  Method* Aj1 = A->FindVirtualMethod("j1", "()V");
-  Method* Aj2 = A->FindVirtualMethod("j2", "()V");
+  AbstractMethod* Ii = I->FindVirtualMethod("i", "()V");
+  AbstractMethod* Jj1 = J->FindVirtualMethod("j1", "()V");
+  AbstractMethod* Jj2 = J->FindVirtualMethod("j2", "()V");
+  AbstractMethod* Kj1 = K->FindInterfaceMethod("j1", "()V");
+  AbstractMethod* Kj2 = K->FindInterfaceMethod("j2", "()V");
+  AbstractMethod* Kk = K->FindInterfaceMethod("k", "()V");
+  AbstractMethod* Ai = A->FindVirtualMethod("i", "()V");
+  AbstractMethod* Aj1 = A->FindVirtualMethod("j1", "()V");
+  AbstractMethod* Aj2 = A->FindVirtualMethod("j2", "()V");
   ASSERT_TRUE(Ii != NULL);
   ASSERT_TRUE(Jj1 != NULL);
   ASSERT_TRUE(Jj2 != NULL);
@@ -984,8 +1004,8 @@
   CHECK(dex_file != NULL);
 
   Class* klass = class_linker_->FindClass("LStaticsFromCode;", class_loader.get());
-  Method* clinit = klass->FindDirectMethod("<clinit>", "()V");
-  Method* getS0 = klass->FindDirectMethod("getS0", "()Ljava/lang/Object;");
+  AbstractMethod* clinit = klass->FindDirectMethod("<clinit>", "()V");
+  AbstractMethod* getS0 = klass->FindDirectMethod("getS0", "()Ljava/lang/Object;");
   const DexFile::StringId* string_id = dex_file->FindStringId("LStaticsFromCode;");
   ASSERT_TRUE(string_id != NULL);
   const DexFile::TypeId* type_id = dex_file->FindTypeId(dex_file->GetIndexForStringId(*string_id));
diff --git a/src/common_test.h b/src/common_test.h
index dee40e3..6994ac3 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -193,7 +193,7 @@
                                      const uint32_t* mapping_table,
                                      const uint16_t* vmap_table,
                                      const uint8_t* gc_map,
-                                     const Method::InvokeStub* invoke_stub) {
+                                     const AbstractMethod::InvokeStub* invoke_stub) {
       return OatFile::OatMethod(NULL,
                                 reinterpret_cast<uint32_t>(code),
                                 frame_size_in_bytes,
@@ -209,7 +209,7 @@
                                 );
   }
 
-  void MakeExecutable(Method* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  void MakeExecutable(AbstractMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     CHECK(method != NULL);
 
     MethodHelper mh(method);
@@ -219,8 +219,8 @@
 
     const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode();
     MakeExecutable(invoke_stub);
-    const Method::InvokeStub* method_invoke_stub =
-        reinterpret_cast<const Method::InvokeStub*>(
+    const AbstractMethod::InvokeStub* method_invoke_stub =
+        reinterpret_cast<const AbstractMethod::InvokeStub*>(
           CompiledCode::CodePointer(&invoke_stub[0],
                                     compiled_invoke_stub->GetInstructionSet()));
 
@@ -479,7 +479,7 @@
     }
   }
 
-  void CompileMethod(Method* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  void CompileMethod(AbstractMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     CHECK(method != NULL);
     compiler_->CompileOne(method);
     MakeExecutable(method);
@@ -495,7 +495,7 @@
     std::string class_descriptor(DotToDescriptor(class_name));
     Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader);
     CHECK(klass != NULL) << "Class not found " << class_name;
-    Method* method = klass->FindDirectMethod(method_name, signature);
+    AbstractMethod* method = klass->FindDirectMethod(method_name, signature);
     CHECK(method != NULL) << "Direct method not found: "
                           << class_name << "." << method_name << signature;
     CompileMethod(method);
@@ -509,7 +509,7 @@
     std::string class_descriptor(DotToDescriptor(class_name));
     Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader);
     CHECK(klass != NULL) << "Class not found " << class_name;
-    Method* method = klass->FindVirtualMethod(method_name, signature);
+    AbstractMethod* method = klass->FindVirtualMethod(method_name, signature);
     CHECK(method != NULL) << "Virtual method not found: "
                           << class_name << "." << method_name << signature;
     CompileMethod(method);
diff --git a/src/common_throws.cc b/src/common_throws.cc
index 758e03b..7ab5614 100644
--- a/src/common_throws.cc
+++ b/src/common_throws.cc
@@ -26,7 +26,7 @@
 
 namespace art {
 
-static void AddReferrerLocation(std::ostream& os, const Method* referrer)
+static void AddReferrerLocation(std::ostream& os, const AbstractMethod* referrer)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   if (referrer != NULL) {
     ClassHelper kh(referrer->GetDeclaringClass());
@@ -58,7 +58,7 @@
   Thread::Current()->ThrowNewException("Ljava/lang/NullPointerException;", msg.str().c_str());
 }
 
-void ThrowNullPointerExceptionForMethodAccess(Method* caller, uint32_t method_idx,
+void ThrowNullPointerExceptionForMethodAccess(AbstractMethod* caller, uint32_t method_idx,
                                               InvokeType type) {
   DexCache* dex_cache = caller->GetDeclaringClass()->GetDexCache();
   const DexFile& dex_file = Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache);
@@ -68,7 +68,7 @@
   Thread::Current()->ThrowNewException("Ljava/lang/NullPointerException;", msg.str().c_str());
 }
 
-void ThrowNullPointerExceptionFromDexPC(Method* throw_method, uint32_t dex_pc) {
+void ThrowNullPointerExceptionFromDexPC(AbstractMethod* throw_method, uint32_t dex_pc) {
   const DexFile::CodeItem* code = MethodHelper(throw_method).GetCodeItem();
   CHECK_LT(dex_pc, code->insns_size_in_code_units_);
   const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
@@ -155,8 +155,8 @@
 }
 
 void ThrowIllegalAccessErrorClassForMethodDispatch(Class* referrer, Class* accessed,
-                                                   const Method* caller,
-                                                   const Method* called,
+                                                   const AbstractMethod* caller,
+                                                   const AbstractMethod* called,
                                                    InvokeType type) {
   std::ostringstream msg;
   msg << "Illegal class access ('" << PrettyDescriptor(referrer) << "' attempting to access '"
@@ -166,7 +166,7 @@
   Thread::Current()->ThrowNewException("Ljava/lang/IllegalAccessError;", msg.str().c_str());
 }
 
-void ThrowIllegalAccessErrorMethod(Class* referrer, Method* accessed) {
+void ThrowIllegalAccessErrorMethod(Class* referrer, AbstractMethod* accessed) {
   std::ostringstream msg;
   msg << "Method '" << PrettyMethod(accessed) << "' is inaccessible to class '"
       << PrettyDescriptor(referrer) << "'";
@@ -182,7 +182,7 @@
   Thread::Current()->ThrowNewException("Ljava/lang/IllegalAccessError;", msg.str().c_str());
 }
 
-void ThrowIllegalAccessErrorFinalField(const Method* referrer, Field* accessed) {
+void ThrowIllegalAccessErrorFinalField(const AbstractMethod* referrer, Field* accessed) {
   std::ostringstream msg;
   msg << "Final field '" << PrettyField(accessed, false) << "' cannot be written to by method '"
       << PrettyMethod(referrer) << "'";
@@ -193,7 +193,7 @@
 // IncompatibleClassChangeError
 
 void ThrowIncompatibleClassChangeError(InvokeType expected_type, InvokeType found_type,
-                                       Method* method, const Method* referrer) {
+                                       AbstractMethod* method, const AbstractMethod* referrer) {
   std::ostringstream msg;
   msg << "The method '" << PrettyMethod(method) << "' was expected to be of type "
       << expected_type << " but instead was found to be of type " << found_type;
@@ -202,9 +202,9 @@
                                        msg.str().c_str());
 }
 
-void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(const Method* interface_method,
+void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(const AbstractMethod* interface_method,
                                                                 Object* this_object,
-                                                                const Method* referrer) {
+                                                                const AbstractMethod* referrer) {
   // Referrer is calling interface_method on this_object, however, the interface_method isn't
   // implemented by this_object.
   CHECK(this_object != NULL);
@@ -219,7 +219,7 @@
 }
 
 void ThrowIncompatibleClassChangeErrorField(const Field* resolved_field, bool is_static,
-                                            const Method* referrer) {
+                                            const AbstractMethod* referrer) {
   std::ostringstream msg;
   msg << "Expected '" << PrettyField(resolved_field) << "' to be a "
       << (is_static ? "static" : "instance") << " field" << " rather than a "
@@ -232,7 +232,7 @@
 // NoSuchMethodError
 
 void ThrowNoSuchMethodError(InvokeType type, Class* c, const StringPiece& name,
-                            const StringPiece& signature, const Method* referrer) {
+                            const StringPiece& signature, const AbstractMethod* referrer) {
   std::ostringstream msg;
   ClassHelper kh(c);
   msg << "No " << type << " method " << name << signature
@@ -241,7 +241,7 @@
   Thread::Current()->ThrowNewException("Ljava/lang/NoSuchMethodError;", msg.str().c_str());
 }
 
-void ThrowNoSuchMethodError(uint32_t method_idx, const Method* referrer) {
+void ThrowNoSuchMethodError(uint32_t method_idx, const AbstractMethod* referrer) {
   DexCache* dex_cache = referrer->GetDeclaringClass()->GetDexCache();
   const DexFile& dex_file = Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache);
   std::ostringstream msg;
diff --git a/src/common_throws.h b/src/common_throws.h
index ca2211f..e0766b6 100644
--- a/src/common_throws.h
+++ b/src/common_throws.h
@@ -27,10 +27,10 @@
 void ThrowNullPointerExceptionForFieldAccess(Field* field, bool is_read)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-void ThrowNullPointerExceptionForMethodAccess(Method* caller, uint32_t method_idx, InvokeType type)
+void ThrowNullPointerExceptionForMethodAccess(AbstractMethod* caller, uint32_t method_idx, InvokeType type)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-void ThrowNullPointerExceptionFromDexPC(Method* throw_method, uint32_t dex_pc)
+void ThrowNullPointerExceptionFromDexPC(AbstractMethod* throw_method, uint32_t dex_pc)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 // IllegalAccessError
@@ -39,41 +39,41 @@
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 void ThrowIllegalAccessErrorClassForMethodDispatch(Class* referrer, Class* accessed,
-                                                   const Method* caller, const Method* called,
+                                                   const AbstractMethod* caller, const AbstractMethod* called,
                                                    InvokeType type)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-void ThrowIllegalAccessErrorMethod(Class* referrer, Method* accessed)
+void ThrowIllegalAccessErrorMethod(Class* referrer, AbstractMethod* accessed)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 void ThrowIllegalAccessErrorField(Class* referrer, Field* accessed)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-void ThrowIllegalAccessErrorFinalField(const Method* referrer, Field* accessed)
+void ThrowIllegalAccessErrorFinalField(const AbstractMethod* referrer, Field* accessed)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 // IncompatibleClassChangeError
 
 void ThrowIncompatibleClassChangeError(InvokeType expected_type, InvokeType found_type,
-                                       Method* method, const Method* referrer)
+                                       AbstractMethod* method, const AbstractMethod* referrer)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(const Method* interface_method,
+void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(const AbstractMethod* interface_method,
                                                                 Object* this_object,
-                                                                const Method* referrer)
+                                                                const AbstractMethod* referrer)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 void ThrowIncompatibleClassChangeErrorField(const Field* resolved_field, bool is_static,
-                                            const Method* referrer)
+                                            const AbstractMethod* referrer)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 // NoSuchMethodError
 
 void ThrowNoSuchMethodError(InvokeType type, Class* c, const StringPiece& name,
-                            const StringPiece& signature, const Method* referrer)
+                            const StringPiece& signature, const AbstractMethod* referrer)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-void ThrowNoSuchMethodError(uint32_t method_idx, const Method* referrer)
+void ThrowNoSuchMethodError(uint32_t method_idx, const AbstractMethod* referrer)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 }  // namespace art
diff --git a/src/compiler.cc b/src/compiler.cc
index abbb939..e8bc390 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -498,7 +498,7 @@
   }
 }
 
-void Compiler::CompileOne(const Method* method) {
+void Compiler::CompileOne(const AbstractMethod* method) {
   DCHECK(!Runtime::Current()->IsStarted());
   Thread* self = Thread::Current();
   jobject class_loader;
@@ -682,7 +682,7 @@
                                             class_loader, false);
 }
 
-static Method* ComputeMethodReferencedFromCompilingMethod(ScopedObjectAccess& soa,
+static AbstractMethod* ComputeMethodReferencedFromCompilingMethod(ScopedObjectAccess& soa,
                                                           OatCompilationUnit* mUnit,
                                                           uint32_t method_idx,
                                                           InvokeType type)
@@ -822,7 +822,7 @@
   return false;  // Incomplete knowledge needs slow path.
 }
 
-void Compiler::GetCodeAndMethodForDirectCall(InvokeType type, InvokeType sharp_type, Method* method,
+void Compiler::GetCodeAndMethodForDirectCall(InvokeType type, InvokeType sharp_type, AbstractMethod* method,
                                              uintptr_t& direct_code, uintptr_t& direct_method) {
   direct_code = 0;
   direct_method = 0;
@@ -866,7 +866,7 @@
   vtable_idx = -1;
   direct_code = 0;
   direct_method = 0;
-  Method* resolved_method =
+  AbstractMethod* resolved_method =
       ComputeMethodReferencedFromCompilingMethod(soa, mUnit, method_idx, type);
   if (resolved_method != NULL) {
     // Don't try to fast-path if we don't understand the caller's class or this appears to be an
@@ -1156,7 +1156,7 @@
     it.Next();
   }
   while (it.HasNextDirectMethod()) {
-    Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
+    AbstractMethod* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
                                                  class_loader, NULL, it.GetMethodInvokeType(class_def));
     if (method == NULL) {
       CHECK(self->IsExceptionPending());
@@ -1165,7 +1165,7 @@
     it.Next();
   }
   while (it.HasNextVirtualMethod()) {
-    Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
+    AbstractMethod* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
                                                  class_loader, NULL, it.GetMethodInvokeType(class_def));
     if (method == NULL) {
       CHECK(self->IsExceptionPending());
diff --git a/src/compiler.h b/src/compiler.h
index 759fcd3..a238b88 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -56,7 +56,7 @@
       LOCKS_EXCLUDED(Locks::mutator_lock_);
 
   // Compile a single Method
-  void CompileOne(const Method* method)
+  void CompileOne(const AbstractMethod* method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   bool IsDebuggingSupported() {
@@ -229,7 +229,7 @@
 
  private:
   // Compute constant code and method pointers when possible
-  void GetCodeAndMethodForDirectCall(InvokeType type, InvokeType sharp_type, Method* method,
+  void GetCodeAndMethodForDirectCall(InvokeType type, InvokeType sharp_type, AbstractMethod* method,
                                      uintptr_t& direct_code, uintptr_t& direct_method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -350,11 +350,11 @@
   CompilerEnableAutoElfLoadingFn compiler_enable_auto_elf_loading_;
 
   typedef const void* (*CompilerGetMethodCodeAddrFn)
-      (const Compiler& compiler, const CompiledMethod* cm, const Method* method);
+      (const Compiler& compiler, const CompiledMethod* cm, const AbstractMethod* method);
   CompilerGetMethodCodeAddrFn compiler_get_method_code_addr_;
 
-  typedef const Method::InvokeStub* (*CompilerGetMethodInvokeStubAddrFn)
-      (const Compiler& compiler, const CompiledInvokeStub* cm, const Method* method);
+  typedef const AbstractMethod::InvokeStub* (*CompilerGetMethodInvokeStubAddrFn)
+      (const Compiler& compiler, const CompiledInvokeStub* cm, const AbstractMethod* method);
   CompilerGetMethodInvokeStubAddrFn compiler_get_method_invoke_stub_addr_;
 #endif
 
diff --git a/src/compiler/codegen/GenCommon.cc b/src/compiler/codegen/GenCommon.cc
index 5593151..99a76da 100644
--- a/src/compiler/codegen/GenCommon.cc
+++ b/src/compiler/codegen/GenCommon.cc
@@ -698,7 +698,7 @@
       RegLocation rlMethod  = loadCurrMethod(cUnit);
       rBase = oatAllocTemp(cUnit);
       loadWordDisp(cUnit, rlMethod.lowReg,
-                   Method::DeclaringClassOffset().Int32Value(), rBase);
+                   AbstractMethod::DeclaringClassOffset().Int32Value(), rBase);
       if (oatIsTemp(cUnit, rlMethod.lowReg)) {
         oatFreeTemp(cUnit, rlMethod.lowReg);
       }
@@ -716,7 +716,7 @@
       rBase = rARG0;
       oatLockTemp(cUnit, rBase);
       loadWordDisp(cUnit, rMethod,
-                   Method::DexCacheInitializedStaticStorageOffset().Int32Value(),
+                   AbstractMethod::DexCacheInitializedStaticStorageOffset().Int32Value(),
                    rBase);
       loadWordDisp(cUnit, rBase,
                    Array::DataOffset(sizeof(Object*)).Int32Value() +
@@ -793,7 +793,7 @@
       RegLocation rlMethod  = loadCurrMethod(cUnit);
       rBase = oatAllocTemp(cUnit);
       loadWordDisp(cUnit, rlMethod.lowReg,
-                   Method::DeclaringClassOffset().Int32Value(), rBase);
+                   AbstractMethod::DeclaringClassOffset().Int32Value(), rBase);
     } else {
       // Medium path, static storage base in a different class which
       // requires checks that the other class is initialized
@@ -808,7 +808,7 @@
       rBase = rARG0;
       oatLockTemp(cUnit, rBase);
       loadWordDisp(cUnit, rMethod,
-                   Method::DexCacheInitializedStaticStorageOffset().Int32Value(),
+                   AbstractMethod::DexCacheInitializedStaticStorageOffset().Int32Value(),
                    rBase);
       loadWordDisp(cUnit, rBase,
                    Array::DataOffset(sizeof(Object*)).Int32Value() +
@@ -1142,7 +1142,7 @@
   } else {
     // We're don't need access checks, load type from dex cache
     int32_t dex_cache_offset =
-        Method::DexCacheResolvedTypesOffset().Int32Value();
+        AbstractMethod::DexCacheResolvedTypesOffset().Int32Value();
     loadWordDisp(cUnit, rlMethod.lowReg, dex_cache_offset, resReg);
     int32_t offset_of_type =
         Array::DataOffset(sizeof(Class*)).Int32Value() + (sizeof(Class*)
@@ -1197,7 +1197,7 @@
     oatLockCallTemps(cUnit); // Using explicit registers
     loadCurrMethodDirect(cUnit, rARG2);
     loadWordDisp(cUnit, rARG2,
-                 Method::DexCacheStringsOffset().Int32Value(), rARG0);
+                 AbstractMethod::DexCacheStringsOffset().Int32Value(), rARG0);
     // Might call out to helper, which will return resolved string in rRET0
 #if !defined(TARGET_X86)
     int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pResolveStringFromCode));
@@ -1233,7 +1233,7 @@
     int resReg = oatAllocTemp(cUnit);
     RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
     loadWordDisp(cUnit, rlMethod.lowReg,
-                 Method::DexCacheStringsOffset().Int32Value(), resReg);
+                 AbstractMethod::DexCacheStringsOffset().Int32Value(), resReg);
     loadWordDisp(cUnit, resReg, offset_of_string, rlResult.lowReg);
     storeValue(cUnit, rlDest, rlResult);
   }
@@ -1287,7 +1287,7 @@
     // Load dex cache entry into classReg (rARG2)
     loadValueDirectFixed(cUnit, rlSrc, rARG0);  // rARG0 <= ref
     loadWordDisp(cUnit, rARG1,
-                 Method::DexCacheResolvedTypesOffset().Int32Value(), classReg);
+                 AbstractMethod::DexCacheResolvedTypesOffset().Int32Value(), classReg);
     int32_t offset_of_type =
         Array::DataOffset(sizeof(Class*)).Int32Value() + (sizeof(Class*)
         * type_idx);
@@ -1369,7 +1369,7 @@
   } else {
     // Load dex cache entry into classReg (rARG2)
     loadWordDisp(cUnit, rARG1,
-                 Method::DexCacheResolvedTypesOffset().Int32Value(), classReg);
+                 AbstractMethod::DexCacheResolvedTypesOffset().Int32Value(), classReg);
     int32_t offset_of_type =
         Array::DataOffset(sizeof(Class*)).Int32Value() +
         (sizeof(Class*) * type_idx);
diff --git a/src/compiler/codegen/GenInvoke.cc b/src/compiler/codegen/GenInvoke.cc
index ba580f8..3cc7c93 100644
--- a/src/compiler/codegen/GenInvoke.cc
+++ b/src/compiler/codegen/GenInvoke.cc
@@ -193,7 +193,7 @@
       break;
     case 1:  // Get method->dex_cache_resolved_methods_
       loadWordDisp(cUnit, rARG0,
-        Method::DexCacheResolvedMethodsOffset().Int32Value(),
+        AbstractMethod::DexCacheResolvedMethodsOffset().Int32Value(),
         rARG0);
       // Set up direct code if known.
       if (directCode != 0) {
@@ -224,7 +224,7 @@
 #if !defined(TARGET_X86)
     case 3:  // Grab the code from the method*
       if (directCode == 0) {
-        loadWordDisp(cUnit, rARG0, Method::GetCodeOffset().Int32Value(),
+        loadWordDisp(cUnit, rARG0, AbstractMethod::GetCodeOffset().Int32Value(),
                      rINVOKE_TGT);
       }
       break;
@@ -273,7 +273,7 @@
       break;
 #if !defined(TARGET_X86)
     case 4: // Get the compiled code address [uses rARG0, sets rINVOKE_TGT]
-      loadWordDisp(cUnit, rARG0, Method::GetCodeOffset().Int32Value(),
+      loadWordDisp(cUnit, rARG0, AbstractMethod::GetCodeOffset().Int32Value(),
                    rINVOKE_TGT);
       break;
 #endif
diff --git a/src/compiler/codegen/MethodCodegenDriver.cc b/src/compiler/codegen/MethodCodegenDriver.cc
index 7d612b0..8269f8b 100644
--- a/src/compiler/codegen/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/MethodCodegenDriver.cc
@@ -129,7 +129,7 @@
   callInst = opReg(cUnit, kOpBlx, rINVOKE_TGT);
 #else
   if (fastPath && info->type != kInterface) {
-    callInst = opMem(cUnit, kOpBlx, rARG0, Method::GetCodeOffset().Int32Value());
+    callInst = opMem(cUnit, kOpBlx, rARG0, AbstractMethod::GetCodeOffset().Int32Value());
   } else {
     int trampoline = 0;
     switch (info->type) {
diff --git a/src/compiler_llvm/compiler_llvm.h b/src/compiler_llvm/compiler_llvm.h
index e9ccd4d..39223ef 100644
--- a/src/compiler_llvm/compiler_llvm.h
+++ b/src/compiler_llvm/compiler_llvm.h
@@ -36,7 +36,7 @@
   class CompiledMethod;
   class Compiler;
   class OatCompilationUnit;
-  class Method;
+  class AbstractMethod;
 }
 
 
diff --git a/src/compiler_llvm/gbc_expander.cc b/src/compiler_llvm/gbc_expander.cc
index d482526..bcca08d 100644
--- a/src/compiler_llvm/gbc_expander.cc
+++ b/src/compiler_llvm/gbc_expander.cc
@@ -655,7 +655,7 @@
 llvm::Value*
 GBCExpanderPass::EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx) {
   llvm::Value* static_storage_dex_cache_addr =
-    EmitLoadDexCacheAddr(art::Method::DexCacheInitializedStaticStorageOffset());
+    EmitLoadDexCacheAddr(art::AbstractMethod::DexCacheInitializedStaticStorageOffset());
 
   llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
 
@@ -665,7 +665,7 @@
 llvm::Value*
 GBCExpanderPass::EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx) {
   llvm::Value* resolved_type_dex_cache_addr =
-    EmitLoadDexCacheAddr(art::Method::DexCacheResolvedTypesOffset());
+    EmitLoadDexCacheAddr(art::AbstractMethod::DexCacheResolvedTypesOffset());
 
   llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
 
@@ -675,7 +675,7 @@
 llvm::Value* GBCExpanderPass::
 EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx) {
   llvm::Value* resolved_method_dex_cache_addr =
-    EmitLoadDexCacheAddr(art::Method::DexCacheResolvedMethodsOffset());
+    EmitLoadDexCacheAddr(art::AbstractMethod::DexCacheResolvedMethodsOffset());
 
   llvm::Value* method_idx_value = irb_.getPtrEquivInt(method_idx);
 
@@ -685,7 +685,7 @@
 llvm::Value* GBCExpanderPass::
 EmitLoadDexCacheStringFieldAddr(uint32_t string_idx) {
   llvm::Value* string_dex_cache_addr =
-    EmitLoadDexCacheAddr(art::Method::DexCacheStringsOffset());
+    EmitLoadDexCacheAddr(art::AbstractMethod::DexCacheStringsOffset());
 
   llvm::Value* string_idx_value = irb_.getPtrEquivInt(string_idx);
 
@@ -983,7 +983,7 @@
 llvm::Value*
 GBCExpanderPass::Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr) {
   return irb_.LoadFromObjectOffset(method_object_addr,
-                                   art::Method::DeclaringClassOffset().Int32Value(),
+                                   art::AbstractMethod::DeclaringClassOffset().Int32Value(),
                                    irb_.getJObjectTy(),
                                    kTBAAConstJObject);
 }
@@ -1035,7 +1035,7 @@
 
   llvm::Value* code_addr =
     irb_.LoadFromObjectOffset(callee_method_object_addr,
-                              art::Method::GetCodeOffset().Int32Value(),
+                              art::AbstractMethod::GetCodeOffset().Int32Value(),
                               callee_method_type->getPointerTo(),
                               kTBAAJRuntime);
 
@@ -1710,7 +1710,7 @@
 
       static_storage_addr =
         irb_.LoadFromObjectOffset(method_object_addr,
-                                  art::Method::DeclaringClassOffset().Int32Value(),
+                                  art::AbstractMethod::DeclaringClassOffset().Int32Value(),
                                   irb_.getJObjectTy(),
                                   kTBAAConstJObject);
     } else {
@@ -1791,7 +1791,7 @@
 
       static_storage_addr =
         irb_.LoadFromObjectOffset(method_object_addr,
-                                  art::Method::DeclaringClassOffset().Int32Value(),
+                                  art::AbstractMethod::DeclaringClassOffset().Int32Value(),
                                   irb_.getJObjectTy(),
                                   kTBAAConstJObject);
     } else {
@@ -2168,7 +2168,7 @@
   } else {
     code_addr =
       irb_.LoadFromObjectOffset(callee_method_object_addr,
-                                art::Method::GetCodeOffset().Int32Value(),
+                                art::AbstractMethod::GetCodeOffset().Int32Value(),
                                 GetFunctionType(callee_method_idx, is_static)->getPointerTo(),
                                 kTBAAJRuntime);
   }
diff --git a/src/compiler_llvm/jni_compiler.cc b/src/compiler_llvm/jni_compiler.cc
index 8bb8b87..5bc3bfc 100644
--- a/src/compiler_llvm/jni_compiler.cc
+++ b/src/compiler_llvm/jni_compiler.cc
@@ -80,7 +80,7 @@
     // Load class object
     this_object_or_class_object =
         irb_.LoadFromObjectOffset(method_object_addr,
-                                  Method::DeclaringClassOffset().Int32Value(),
+                                  AbstractMethod::DeclaringClassOffset().Int32Value(),
                                   irb_.getJObjectTy(),
                                   kTBAAConstJObject);
   }
@@ -124,7 +124,7 @@
   // Get callee code_addr
   llvm::Value* code_addr =
       irb_.LoadFromObjectOffset(method_object_addr,
-                                Method::NativeMethodOffset().Int32Value(),
+                                AbstractMethod::NativeMethodOffset().Int32Value(),
                                 GetFunctionType(method_idx_, is_static, true)->getPointerTo(),
                                 kTBAAJRuntime);
 
diff --git a/src/compiler_llvm/jni_compiler.h b/src/compiler_llvm/jni_compiler.h
index 80494b6..c428775 100644
--- a/src/compiler_llvm/jni_compiler.h
+++ b/src/compiler_llvm/jni_compiler.h
@@ -26,7 +26,7 @@
   class Compiler;
   class DexCache;
   class DexFile;
-  class Method;
+  class AbstractMethod;
   class OatCompilationUnit;
 }
 
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index a74a6a4..61fffbe 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -2547,7 +2547,7 @@
 
       static_storage_addr =
         irb_.LoadFromObjectOffset(method_object_addr,
-                                  Method::DeclaringClassOffset().Int32Value(),
+                                  AbstractMethod::DeclaringClassOffset().Int32Value(),
                                   irb_.getJObjectTy(),
                                   kTBAAConstJObject);
     } else {
@@ -2626,7 +2626,7 @@
 
       static_storage_addr =
         irb_.LoadFromObjectOffset(method_object_addr,
-                                  Method::DeclaringClassOffset().Int32Value(),
+                                  AbstractMethod::DeclaringClassOffset().Int32Value(),
                                   irb_.getJObjectTy(),
                                   kTBAAConstJObject);
     } else {
@@ -2815,7 +2815,7 @@
   } else {
     code_addr =
       irb_.LoadFromObjectOffset(callee_method_object_addr,
-                                Method::GetCodeOffset().Int32Value(),
+                                AbstractMethod::GetCodeOffset().Int32Value(),
                                 GetFunctionType(callee_method_idx, is_static)->getPointerTo(),
                                 kTBAAJRuntime);
   }
@@ -3479,7 +3479,7 @@
 llvm::Value* MethodCompiler::
 EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx) {
   llvm::Value* static_storage_dex_cache_addr =
-    EmitLoadDexCacheAddr(Method::DexCacheInitializedStaticStorageOffset());
+    EmitLoadDexCacheAddr(AbstractMethod::DexCacheInitializedStaticStorageOffset());
 
   llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
 
@@ -3490,7 +3490,7 @@
 llvm::Value* MethodCompiler::
 EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx) {
   llvm::Value* resolved_type_dex_cache_addr =
-    EmitLoadDexCacheAddr(Method::DexCacheResolvedTypesOffset());
+    EmitLoadDexCacheAddr(AbstractMethod::DexCacheResolvedTypesOffset());
 
   llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
 
@@ -3501,7 +3501,7 @@
 llvm::Value* MethodCompiler::
 EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx) {
   llvm::Value* resolved_method_dex_cache_addr =
-    EmitLoadDexCacheAddr(Method::DexCacheResolvedMethodsOffset());
+    EmitLoadDexCacheAddr(AbstractMethod::DexCacheResolvedMethodsOffset());
 
   llvm::Value* method_idx_value = irb_.getPtrEquivInt(method_idx);
 
@@ -3512,7 +3512,7 @@
 llvm::Value* MethodCompiler::
 EmitLoadDexCacheStringFieldAddr(uint32_t string_idx) {
   llvm::Value* string_dex_cache_addr =
-    EmitLoadDexCacheAddr(Method::DexCacheStringsOffset());
+    EmitLoadDexCacheAddr(AbstractMethod::DexCacheStringsOffset());
 
   llvm::Value* string_idx_value = irb_.getPtrEquivInt(string_idx);
 
diff --git a/src/compiler_llvm/runtime_support_llvm.h b/src/compiler_llvm/runtime_support_llvm.h
index c900717..626fe4f 100644
--- a/src/compiler_llvm/runtime_support_llvm.h
+++ b/src/compiler_llvm/runtime_support_llvm.h
@@ -26,7 +26,7 @@
 //----------------------------------------------------------------------------
 
 ShadowFrame* art_push_shadow_frame_from_code(Thread* thread, ShadowFrame* new_shadow_frame,
-                                             Method* method, uint32_t size);
+                                             AbstractMethod* method, uint32_t size);
 
 void art_pop_shadow_frame_from_code(void*);
 
@@ -49,7 +49,7 @@
 
 void art_throw_exception_from_code(Object* exception);
 
-int32_t art_find_catch_block_from_code(Method* current_method,
+int32_t art_find_catch_block_from_code(AbstractMethod* current_method,
                                        uint32_t ti_offset);
 
 
diff --git a/src/compiler_llvm/stub_compiler.cc b/src/compiler_llvm/stub_compiler.cc
index 46c6f21..3ac5f2a 100644
--- a/src/compiler_llvm/stub_compiler.cc
+++ b/src/compiler_llvm/stub_compiler.cc
@@ -142,7 +142,7 @@
 
   // Invoke managed method now!
   llvm::Value* code_field_offset_value =
-    irb_.getPtrEquivInt(Method::GetCodeOffset().Int32Value());
+    irb_.getPtrEquivInt(AbstractMethod::GetCodeOffset().Int32Value());
 
   llvm::Value* code_field_addr =
     irb_.CreatePtrDisp(method_object_addr, code_field_offset_value,
diff --git a/src/compiler_test.cc b/src/compiler_test.cc
index 98b2142..f513511 100644
--- a/src/compiler_test.cc
+++ b/src/compiler_test.cc
@@ -106,7 +106,7 @@
   }
   EXPECT_EQ(dex->NumMethodIds(), dex_cache->NumResolvedMethods());
   for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) {
-    Method* method = dex_cache->GetResolvedMethod(i);
+    AbstractMethod* method = dex_cache->GetResolvedMethod(i);
     EXPECT_TRUE(method != NULL) << "method_idx=" << i
                                 << " " << dex->GetMethodDeclaringClassDescriptor(dex->GetMethodId(i))
                                 << " " << dex->GetMethodName(dex->GetMethodId(i));
diff --git a/src/debugger.cc b/src/debugger.cc
index 87ad446..8b87945 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -95,7 +95,7 @@
 };
 
 struct AllocRecordStackTraceElement {
-  Method* method;
+  AbstractMethod* method;
   uint32_t dex_pc;
 
   int32_t LineNumber() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -119,9 +119,9 @@
 };
 
 struct Breakpoint {
-  Method* method;
+  AbstractMethod* method;
   uint32_t dex_pc;
-  Breakpoint(Method* method, uint32_t dex_pc) : method(method), dex_pc(dex_pc) {}
+  Breakpoint(AbstractMethod* method, uint32_t dex_pc) : method(method), dex_pc(dex_pc) {}
 };
 
 static std::ostream& operator<<(std::ostream& os, const Breakpoint& rhs)
@@ -138,7 +138,7 @@
   JDWP::JdwpStepSize step_size;
   JDWP::JdwpStepDepth step_depth;
 
-  const Method* method;
+  const AbstractMethod* method;
   int32_t line_number; // Or -1 for native methods.
   std::set<uint32_t> dex_pcs;
   int stack_depth;
@@ -181,7 +181,7 @@
 static std::vector<Breakpoint> gBreakpoints GUARDED_BY(gBreakpointsLock);
 static SingleStepControl gSingleStepControl GUARDED_BY(gBreakpointsLock);
 
-static bool IsBreakpoint(Method* m, uint32_t dex_pc)
+static bool IsBreakpoint(AbstractMethod* m, uint32_t dex_pc)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   MutexLock mu(gBreakpointsLock);
   for (size_t i = 0; i < gBreakpoints.size(); ++i) {
@@ -928,7 +928,7 @@
 #endif
 }
 
-static JDWP::MethodId ToMethodId(const Method* m)
+static JDWP::MethodId ToMethodId(const AbstractMethod* m)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #ifdef MOVING_GARBAGE_COLLECTOR
   UNIMPLEMENTED(FATAL);
@@ -946,16 +946,16 @@
 #endif
 }
 
-static Method* FromMethodId(JDWP::MethodId mid)
+static AbstractMethod* FromMethodId(JDWP::MethodId mid)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #ifdef MOVING_GARBAGE_COLLECTOR
   UNIMPLEMENTED(FATAL);
 #else
-  return reinterpret_cast<Method*>(static_cast<uintptr_t>(mid));
+  return reinterpret_cast<AbstractMethod*>(static_cast<uintptr_t>(mid));
 #endif
 }
 
-static void SetLocation(JDWP::JdwpLocation& location, Method* m, uint32_t dex_pc)
+static void SetLocation(JDWP::JdwpLocation& location, AbstractMethod* m, uint32_t dex_pc)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   if (m == NULL) {
     memset(&location, 0, sizeof(location));
@@ -970,7 +970,7 @@
 
 std::string Dbg::GetMethodName(JDWP::RefTypeId, JDWP::MethodId methodId)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  Method* m = FromMethodId(methodId);
+  AbstractMethod* m = FromMethodId(methodId);
   return MethodHelper(m).GetName();
 }
 
@@ -1012,7 +1012,7 @@
   return newSlot;
 }
 
-static uint16_t DemangleSlot(uint16_t slot, Method* m)
+static uint16_t DemangleSlot(uint16_t slot, AbstractMethod* m)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   if (slot == kEclipseWorkaroundSlot) {
     return 0;
@@ -1065,7 +1065,7 @@
   expandBufAdd4BE(pReply, direct_method_count + virtual_method_count);
 
   for (size_t i = 0; i < direct_method_count + virtual_method_count; ++i) {
-    Method* m = (i < direct_method_count) ? c->GetDirectMethod(i) : c->GetVirtualMethod(i - direct_method_count);
+    AbstractMethod* m = (i < direct_method_count) ? c->GetDirectMethod(i) : c->GetVirtualMethod(i - direct_method_count);
     MethodHelper mh(m);
     expandBufAddMethodId(pReply, ToMethodId(m));
     expandBufAddUtf8String(pReply, mh.GetName());
@@ -1109,7 +1109,7 @@
       return true;
     }
   };
-  Method* m = FromMethodId(methodId);
+  AbstractMethod* m = FromMethodId(methodId);
   MethodHelper mh(m);
   uint64_t start, end;
   if (m->IsNative()) {
@@ -1163,7 +1163,7 @@
       ++pContext->variable_count;
     }
   };
-  Method* m = FromMethodId(methodId);
+  AbstractMethod* m = FromMethodId(methodId);
   MethodHelper mh(m);
   const DexFile::CodeItem* code_item = mh.GetCodeItem();
 
@@ -1676,7 +1676,7 @@
     if (frame_id != GetFrameId()) {
       return true;  // continue
     }
-    Method* m = GetMethod();
+    AbstractMethod* m = GetMethod();
     if (m->IsNative() || m->IsStatic()) {
       this_object = NULL;
     } else {
@@ -1690,7 +1690,7 @@
   JDWP::FrameId frame_id;
 };
 
-static Object* GetThis(Thread* self, Method* m, size_t frame_id)
+static Object* GetThis(Thread* self, AbstractMethod* m, size_t frame_id)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   // TODO: should we return the 'this' we passed through to non-static native methods?
   if (m->IsNative() || m->IsStatic()) {
@@ -1742,7 +1742,7 @@
         return true;  // Not our frame, carry on.
       }
       // TODO: check that the tag is compatible with the actual type of the slot!
-      Method* m = GetMethod();
+      AbstractMethod* m = GetMethod();
       uint16_t reg = DemangleSlot(slot_, m);
 
       switch (tag_) {
@@ -1861,7 +1861,7 @@
         return true;  // Not our frame, carry on.
       }
       // TODO: check that the tag is compatible with the actual type of the slot!
-      Method* m = GetMethod();
+      AbstractMethod* m = GetMethod();
       uint16_t reg = DemangleSlot(slot_, m);
 
       switch (tag_) {
@@ -1920,7 +1920,7 @@
   visitor.WalkStack();
 }
 
-void Dbg::PostLocationEvent(const Method* m, int dex_pc, Object* this_object, int event_flags) {
+void Dbg::PostLocationEvent(const AbstractMethod* m, int dex_pc, Object* this_object, int event_flags) {
   Class* c = m->GetDeclaringClass();
 
   JDWP::JdwpLocation location;
@@ -1942,8 +1942,8 @@
 }
 
 void Dbg::PostException(Thread* thread,
-                        JDWP::FrameId throw_frame_id, Method* throw_method, uint32_t throw_dex_pc,
-                        Method* catch_method, uint32_t catch_dex_pc, Throwable* exception) {
+                        JDWP::FrameId throw_frame_id, AbstractMethod* throw_method, uint32_t throw_dex_pc,
+                        AbstractMethod* catch_method, uint32_t catch_dex_pc, Throwable* exception) {
   if (!IsDebuggerActive()) {
     return;
   }
@@ -1993,7 +1993,7 @@
   }
 
   size_t frame_id;
-  Method* m = self->GetCurrentMethod(NULL, &frame_id);
+  AbstractMethod* m = self->GetCurrentMethod(NULL, &frame_id);
   //LOG(INFO) << "UpdateDebugger " << PrettyMethod(m) << "@" << dex_pc << " frame " << frame_id;
 
   if (dex_pc == -1) {
@@ -2097,14 +2097,14 @@
 
 void Dbg::WatchLocation(const JDWP::JdwpLocation* location) {
   MutexLock mu(gBreakpointsLock);
-  Method* m = FromMethodId(location->method_id);
+  AbstractMethod* m = FromMethodId(location->method_id);
   gBreakpoints.push_back(Breakpoint(m, location->dex_pc));
   VLOG(jdwp) << "Set breakpoint #" << (gBreakpoints.size() - 1) << ": " << gBreakpoints[gBreakpoints.size() - 1];
 }
 
 void Dbg::UnwatchLocation(const JDWP::JdwpLocation* location) {
   MutexLock mu(gBreakpointsLock);
-  Method* m = FromMethodId(location->method_id);
+  AbstractMethod* m = FromMethodId(location->method_id);
   for (size_t i = 0; i < gBreakpoints.size(); ++i) {
     if (gBreakpoints[i].method == m && gBreakpoints[i].dex_pc == location->dex_pc) {
       VLOG(jdwp) << "Removed breakpoint #" << i << ": " << gBreakpoints[i];
@@ -2150,7 +2150,7 @@
     // annotalysis.
     bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS {
       gBreakpointsLock.AssertHeld();
-      const Method* m = GetMethod();
+      const AbstractMethod* m = GetMethod();
       if (!m->IsRuntimeMethod()) {
         ++gSingleStepControl.stack_depth;
         if (gSingleStepControl.method == NULL) {
@@ -2215,7 +2215,7 @@
     uint32_t last_pc;
   };
   gSingleStepControl.dex_pcs.clear();
-  const Method* m = gSingleStepControl.method;
+  const AbstractMethod* m = gSingleStepControl.method;
   if (m->IsNative()) {
     gSingleStepControl.line_number = -1;
   } else {
@@ -2352,7 +2352,7 @@
       return status;
     }
 
-    Method* m = FromMethodId(methodId);
+    AbstractMethod* m = FromMethodId(methodId);
     if (m->IsStatic() != (receiver == NULL)) {
       return JDWP::ERR_INVALID_METHODID;
     }
@@ -2461,9 +2461,9 @@
   soa.Self()->ClearException();
 
   // Translate the method through the vtable, unless the debugger wants to suppress it.
-  Method* m = pReq->method_;
+  AbstractMethod* m = pReq->method_;
   if ((pReq->options_ & JDWP::INVOKE_NONVIRTUAL) == 0 && pReq->receiver_ != NULL) {
-    Method* actual_method = pReq->class_->FindVirtualMethodForVirtualOrInterface(pReq->method_);
+    AbstractMethod* actual_method = pReq->class_->FindVirtualMethodForVirtualOrInterface(pReq->method_);
     if (actual_method != m) {
       VLOG(jdwp) << "ExecuteMethod translated " << PrettyMethod(m) << " to " << PrettyMethod(actual_method);
       m = actual_method;
@@ -3128,7 +3128,7 @@
     if (depth >= kMaxAllocRecordStackDepth) {
       return false;
     }
-    Method* m = GetMethod();
+    AbstractMethod* m = GetMethod();
     if (!m->IsRuntimeMethod()) {
       record->stack[depth].method = m;
       record->stack[depth].dex_pc = GetDexPc();
@@ -3211,7 +3211,7 @@
               << PrettyClass(record->type);
 
     for (size_t stack_frame = 0; stack_frame < kMaxAllocRecordStackDepth; ++stack_frame) {
-      const Method* m = record->stack[stack_frame].method;
+      const AbstractMethod* m = record->stack[stack_frame].method;
       if (m == NULL) {
         break;
       }
@@ -3330,7 +3330,7 @@
 
     MethodHelper mh;
     for (size_t i = 0; i < kMaxAllocRecordStackDepth; i++) {
-      Method* m = record->stack[i].method;
+      AbstractMethod* m = record->stack[i].method;
       if (m != NULL) {
         mh.ChangeMethod(m);
         class_names.Add(mh.GetDeclaringClassDescriptor());
diff --git a/src/debugger.h b/src/debugger.h
index 43590f8..c577590 100644
--- a/src/debugger.h
+++ b/src/debugger.h
@@ -56,7 +56,7 @@
   Object* receiver_;      /* not used for ClassType.InvokeMethod */
   Object* thread_;
   Class* class_;
-  Method* method_;
+  AbstractMethod* method_;
   uint32_t arg_count_;
   uint64_t* arg_values_;   /* will be NULL if arg_count_ == 0 */
   uint32_t options_;
@@ -281,10 +281,10 @@
     kMethodEntry    = 0x04,
     kMethodExit     = 0x08,
   };
-  static void PostLocationEvent(const Method* method, int pcOffset, Object* thisPtr, int eventFlags)
+  static void PostLocationEvent(const AbstractMethod* method, int pcOffset, Object* thisPtr, int eventFlags)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  static void PostException(Thread* thread, JDWP::FrameId throw_frame_id, Method* throw_method,
-                            uint32_t throw_dex_pc, Method* catch_method, uint32_t catch_dex_pc,
+  static void PostException(Thread* thread, JDWP::FrameId throw_frame_id, AbstractMethod* throw_method,
+                            uint32_t throw_dex_pc, AbstractMethod* catch_method, uint32_t catch_dex_pc,
                             Throwable* exception)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   static void PostThreadStart(Thread* t)
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index 2a6a220..05ff0c0 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -375,12 +375,12 @@
         reinterpret_cast<std::set<std::pair<uint16_t, const DexFile*> >*>(arg);
     MethodHelper mh;
     for (size_t i = 0; i < c->NumVirtualMethods(); ++i) {
-      Method* m = c->GetVirtualMethod(i);
+      AbstractMethod* m = c->GetVirtualMethod(i);
       mh.ChangeMethod(m);
       ResolveExceptionsForMethod(&mh, *exceptions_to_resolve);
     }
     for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
-      Method* m = c->GetDirectMethod(i);
+      AbstractMethod* m = c->GetDirectMethod(i);
       mh.ChangeMethod(m);
       ResolveExceptionsForMethod(&mh, *exceptions_to_resolve);
     }
diff --git a/src/dex_cache.cc b/src/dex_cache.cc
index 02a8a55..adb889b 100644
--- a/src/dex_cache.cc
+++ b/src/dex_cache.cc
@@ -23,29 +23,34 @@
 
 namespace art {
 
-void DexCache::Init(String* location,
+void DexCache::Init(const DexFile* dex_file,
+                    String* location,
                     ObjectArray<String>* strings,
                     ObjectArray<Class>* resolved_types,
-                    ObjectArray<Method>* resolved_methods,
+                    ObjectArray<AbstractMethod>* resolved_methods,
                     ObjectArray<Field>* resolved_fields,
                     ObjectArray<StaticStorageBase>* initialized_static_storage) {
+  CHECK(dex_file != NULL);
   CHECK(location != NULL);
   CHECK(strings != NULL);
   CHECK(resolved_types != NULL);
   CHECK(resolved_methods != NULL);
   CHECK(resolved_fields != NULL);
   CHECK(initialized_static_storage != NULL);
-  Set(kLocation,                 location);
-  Set(kStrings,                  strings);
-  Set(kResolvedTypes,            resolved_types);
-  Set(kResolvedMethods,          resolved_methods);
-  Set(kResolvedFields,           resolved_fields);
-  Set(kInitializedStaticStorage, initialized_static_storage);
+
+  SetFieldPtr(OFFSET_OF_OBJECT_MEMBER(DexCache, dex_file_), dex_file, false);
+  SetFieldObject(OFFSET_OF_OBJECT_MEMBER(DexCache, location_), location, false);
+  SetFieldObject(StringsOffset(), strings, false);
+  SetFieldObject(OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_types_), resolved_types, false);
+  SetFieldObject(ResolvedMethodsOffset(), resolved_methods, false);
+  SetFieldObject(ResolvedFieldsOffset(), resolved_fields, false);
+  SetFieldObject(OFFSET_OF_OBJECT_MEMBER(DexCache, initialized_static_storage_),
+                 initialized_static_storage, false);
 
   Runtime* runtime = Runtime::Current();
   if (runtime->HasResolutionMethod()) {
     // Initialize the resolve methods array to contain trampolines for resolution.
-    Method* trampoline = runtime->GetResolutionMethod();
+    AbstractMethod* trampoline = runtime->GetResolutionMethod();
     size_t length = resolved_methods->GetLength();
     for (size_t i = 0; i < length; i++) {
       resolved_methods->SetWithoutChecks(i, trampoline);
@@ -53,10 +58,10 @@
   }
 }
 
-void DexCache::Fixup(Method* trampoline) {
+void DexCache::Fixup(AbstractMethod* trampoline) {
   // Fixup the resolve methods array to contain trampoline for resolution.
   CHECK(trampoline != NULL);
-  ObjectArray<Method>* resolved_methods = down_cast<ObjectArray<Method>*>(Get(kResolvedMethods));
+  ObjectArray<AbstractMethod>* resolved_methods = GetResolvedMethods();
   size_t length = resolved_methods->GetLength();
   for (size_t i = 0; i < length; i++) {
     if (resolved_methods->GetWithoutChecks(i) == NULL) {
diff --git a/src/dex_cache.h b/src/dex_cache.h
index a08c644..8d88dc6 100644
--- a/src/dex_cache.h
+++ b/src/dex_cache.h
@@ -27,39 +27,42 @@
 class Class;
 class Field;
 class ImageWriter;
-class Method;
+class AbstractMethod;
 class String;
 union JValue;
 
-class MANAGED DexCache : public ObjectArray<Object> {
+class MANAGED DexCacheClass : public Class {
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(DexCacheClass);
+};
+
+class MANAGED DexCache : public Object {
  public:
-  void Init(String* location,
+  void Init(const DexFile* dex_file,
+            String* location,
             ObjectArray<String>* strings,
             ObjectArray<Class>* types,
-            ObjectArray<Method>* methods,
+            ObjectArray<AbstractMethod>* methods,
             ObjectArray<Field>* fields,
             ObjectArray<StaticStorageBase>* initialized_static_storage)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void Fixup(Method* trampoline) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void Fixup(AbstractMethod* trampoline) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   String* GetLocation() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return Get(kLocation)->AsString();
+    return GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(DexCache, location_), false);
   }
 
   static MemberOffset StringsOffset() {
-    return MemberOffset(DataOffset(sizeof(Object*)).Int32Value() +
-                        kStrings * sizeof(Object*));
+    return OFFSET_OF_OBJECT_MEMBER(DexCache, strings_);
   }
 
   static MemberOffset ResolvedFieldsOffset() {
-    return MemberOffset(DataOffset(sizeof(Object*)).Int32Value() +
-                        kResolvedFields * sizeof(Object*));
+    return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_fields_);
   }
 
   static MemberOffset ResolvedMethodsOffset() {
-    return MemberOffset(DataOffset(sizeof(Object*)).Int32Value() +
-                        kResolvedMethods * sizeof(Object*));
+    return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_methods_);
   }
 
   size_t NumStrings() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -103,9 +106,9 @@
     GetResolvedTypes()->Set(type_idx, resolved);
   }
 
-  Method* GetResolvedMethod(uint32_t method_idx) const
+  AbstractMethod* GetResolvedMethod(uint32_t method_idx) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    Method* method = GetResolvedMethods()->Get(method_idx);
+    AbstractMethod* method = GetResolvedMethods()->Get(method_idx);
     // Hide resolution trampoline methods from the caller
     if (method != NULL && method->GetDexMethodIndex() == DexFile::kDexNoIndex16) {
       DCHECK(method == Runtime::Current()->GetResolutionMethod());
@@ -115,7 +118,7 @@
     }
   }
 
-  void SetResolvedMethod(uint32_t method_idx, Method* resolved)
+  void SetResolvedMethod(uint32_t method_idx, AbstractMethod* resolved)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     GetResolvedMethods()->Set(method_idx, resolved);
   }
@@ -132,47 +135,49 @@
 
   ObjectArray<String>* GetStrings() const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return static_cast<ObjectArray<String>*>(GetNonNull(kStrings));
-  }
-  ObjectArray<Class>* GetResolvedTypes() const
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return static_cast<ObjectArray<Class>*>(GetNonNull(kResolvedTypes));
-  }
-  ObjectArray<Method>* GetResolvedMethods() const
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return static_cast<ObjectArray<Method>*>(GetNonNull(kResolvedMethods));
-  }
-  ObjectArray<Field>* GetResolvedFields() const
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return static_cast<ObjectArray<Field>*>(GetNonNull(kResolvedFields));
-  }
-  ObjectArray<StaticStorageBase>* GetInitializedStaticStorage() const
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return static_cast<ObjectArray<StaticStorageBase>*>(GetNonNull(kInitializedStaticStorage));
+    return GetFieldObject< ObjectArray<String>* >(StringsOffset(), false);
   }
 
-  static size_t LengthAsArray() {
-    return kMax;
+  ObjectArray<Class>* GetResolvedTypes() const
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return GetFieldObject< ObjectArray<Class>* >(
+        OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_types_), false);
+  }
+
+  ObjectArray<AbstractMethod>* GetResolvedMethods() const
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return GetFieldObject< ObjectArray<AbstractMethod>* >(ResolvedMethodsOffset(), false);
+  }
+
+  ObjectArray<Field>* GetResolvedFields() const
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return GetFieldObject< ObjectArray<Field>* >(ResolvedFieldsOffset(), false);
+  }
+
+  ObjectArray<StaticStorageBase>* GetInitializedStaticStorage() const
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return GetFieldObject< ObjectArray<StaticStorageBase>* >(
+        OFFSET_OF_OBJECT_MEMBER(DexCache, initialized_static_storage_), false);
+  }
+
+  const DexFile* GetDexFile() const {
+    return GetFieldPtr<const DexFile*>(OFFSET_OF_OBJECT_MEMBER(DexCache, dex_file_), false);
+  }
+
+  void SetDexFile(const DexFile* dex_file) {
+    return SetFieldPtr(OFFSET_OF_OBJECT_MEMBER(DexCache, dex_file_), dex_file, false);
   }
 
  private:
-  enum ArrayIndex {
-    kLocation                 = 0,
-    kStrings                  = 1,
-    kResolvedTypes            = 2,
-    kResolvedMethods          = 3,
-    kResolvedFields           = 4,
-    kInitializedStaticStorage = 5,
-    kMax                      = 6,
-  };
+  ObjectArray<StaticStorageBase>* initialized_static_storage_;
+  String* location_;
+  ObjectArray<Object>* resolved_fields_;
+  ObjectArray<AbstractMethod>* resolved_methods_;
+  ObjectArray<Class>* resolved_types_;
+  ObjectArray<String>* strings_;
+  uint32_t dex_file_;
 
-  Object* GetNonNull(ArrayIndex array_index) const
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    Object* obj = Get(array_index);
-    DCHECK(obj != NULL);
-    return obj;
-  }
-
+  friend struct DexCacheOffsets; // for verifying offset information
   DISALLOW_IMPLICIT_CONSTRUCTORS(DexCache);
 };
 
diff --git a/src/dex_file.cc b/src/dex_file.cc
index e763e67..9717134 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -588,7 +588,7 @@
   return descriptor;
 }
 
-int32_t DexFile::GetLineNumFromPC(const Method* method, uint32_t rel_pc) const {
+int32_t DexFile::GetLineNumFromPC(const AbstractMethod* method, uint32_t rel_pc) const {
   // For native method, lineno should be -2 to indicate it is native. Note that
   // "line number == -2" is how libcore tells from StackTraceElement.
   if (method->GetCodeItemOffset() == 0) {
diff --git a/src/dex_file.h b/src/dex_file.h
index 7d39945..d28e684 100644
--- a/src/dex_file.h
+++ b/src/dex_file.h
@@ -775,7 +775,7 @@
   // Returns -2 for native methods (as expected in exception traces).
   //
   // This is used by runtime; therefore use art::Method not art::DexFile::Method.
-  int32_t GetLineNumFromPC(const Method* method, uint32_t rel_pc) const
+  int32_t GetLineNumFromPC(const AbstractMethod* method, uint32_t rel_pc) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void DecodeDebugInfo(const CodeItem* code_item, bool is_static, uint32_t method_idx,
diff --git a/src/exception_test.cc b/src/exception_test.cc
index 6a58210..46184c5 100644
--- a/src/exception_test.cc
+++ b/src/exception_test.cc
@@ -74,8 +74,8 @@
   std::vector<uint32_t> fake_mapping_data_;
   std::vector<uint16_t> fake_vmap_table_data_;
 
-  Method* method_f_;
-  Method* method_g_;
+  AbstractMethod* method_f_;
+  AbstractMethod* method_g_;
 
  private:
   Class* my_klass_;
diff --git a/src/greenland/arm/arm_invoke_stub_compiler.cc b/src/greenland/arm/arm_invoke_stub_compiler.cc
index f14b35f..2360ed7 100644
--- a/src/greenland/arm/arm_invoke_stub_compiler.cc
+++ b/src/greenland/arm/arm_invoke_stub_compiler.cc
@@ -137,7 +137,7 @@
   }
 
   // Load the code pointer we are about to call.
-  __ LoadFromOffset(kLoadWord, IP, R0, Method::GetCodeOffset().Int32Value());
+  __ LoadFromOffset(kLoadWord, IP, R0, AbstractMethod::GetCodeOffset().Int32Value());
 
   // Do the call.
   __ blx(IP);
diff --git a/src/greenland/runtime/support_alloc.cc b/src/greenland/runtime/support_alloc.cc
index 5198903..dd7850d 100644
--- a/src/greenland/runtime/support_alloc.cc
+++ b/src/greenland/runtime/support_alloc.cc
@@ -25,28 +25,28 @@
 namespace {
 
 Object* art_alloc_array_from_code(uint32_t type_idx,
-                                  Method* referrer,
+                                  AbstractMethod* referrer,
                                   uint32_t length,
                                   Thread* thread) {
   return AllocArrayFromCode(type_idx, referrer, length, thread, false);
 }
 
 Object* art_alloc_array_from_code_with_access_check(uint32_t type_idx,
-                                                    Method* referrer,
+                                                    AbstractMethod* referrer,
                                                     uint32_t length,
                                                     Thread* thread) {
   return AllocArrayFromCode(type_idx, referrer, length, thread, true);
 }
 
 Object* art_check_and_alloc_array_from_code(uint32_t type_idx,
-                                            Method* referrer,
+                                            AbstractMethod* referrer,
                                             uint32_t length,
                                             Thread* thread) {
   return CheckAndAllocArrayFromCode(type_idx, referrer, length, thread, false);
 }
 
 Object* art_check_and_alloc_array_from_code_with_access_check(uint32_t type_idx,
-                                                              Method* referrer,
+                                                              AbstractMethod* referrer,
                                                               uint32_t length,
                                                               Thread* thread) {
   return CheckAndAllocArrayFromCode(type_idx, referrer, length, thread, true);
diff --git a/src/greenland/runtime/support_dexcache.cc b/src/greenland/runtime/support_dexcache.cc
index 903e5cc..9d36aad 100644
--- a/src/greenland/runtime/support_dexcache.cc
+++ b/src/greenland/runtime/support_dexcache.cc
@@ -24,7 +24,7 @@
 
 namespace {
 
-Object* art_resolve_string(Method* referrer, uint32_t string_idx) {
+Object* art_resolve_string(AbstractMethod* referrer, uint32_t string_idx) {
   return ResolveStringFromCode(referrer, string_idx);
 }
 
diff --git a/src/greenland/runtime/support_exception.cc b/src/greenland/runtime/support_exception.cc
index 2470051..4bc910a 100644
--- a/src/greenland/runtime/support_exception.cc
+++ b/src/greenland/runtime/support_exception.cc
@@ -25,7 +25,7 @@
 
 namespace {
 
-int32_t art_find_catch_block(Method* current_method, uint32_t ti_offset) {
+int32_t art_find_catch_block(AbstractMethod* current_method, uint32_t ti_offset) {
   Thread* thread = art_get_current_thread();
   Class* exception_type = thread->GetException()->GetClass();
   MethodHelper mh(current_method);
@@ -66,7 +66,7 @@
   Thread* thread = art_get_current_thread();
   NthCallerVisitor visitor(0);
   thread->WalkStack(&visitor);
-  Method* throw_method = visitor.caller;
+  AbstractMethod* throw_method = visitor.caller;
   ThrowNullPointerExceptionFromDexPC(thread, throw_method, dex_pc);
 }
 
diff --git a/src/greenland/runtime/support_field.cc b/src/greenland/runtime/support_field.cc
index 523740f..e5fa814 100644
--- a/src/greenland/runtime/support_field.cc
+++ b/src/greenland/runtime/support_field.cc
@@ -24,7 +24,7 @@
 
 namespace {
 
-Object* art_get_obj_static_from_code(uint32_t field_idx, Method* referrer) {
+Object* art_get_obj_static_from_code(uint32_t field_idx, AbstractMethod* referrer) {
   Field* field = FindFieldFast(field_idx, referrer, false, false, sizeof(Object*));
   if (LIKELY(field != NULL)) {
     return field->GetObj(NULL);
diff --git a/src/greenland/runtime_entry_points.h b/src/greenland/runtime_entry_points.h
index 8cd8ce44..9ee053e 100644
--- a/src/greenland/runtime_entry_points.h
+++ b/src/greenland/runtime_entry_points.h
@@ -27,7 +27,7 @@
 
 namespace art {
 
-class Method;
+class AbstractMethod;
 class Object;
 class Thread;
 
@@ -40,36 +40,36 @@
   //----------------------------------------------------------------------------
   // Exception
   //----------------------------------------------------------------------------
-  int32_t (*FindCatchBlock)(Method* current_method, uint32_t ti_offset);
+  int32_t (*FindCatchBlock)(AbstractMethod* current_method, uint32_t ti_offset);
   void (*ThrowIndexOutOfBounds)(int32_t length, int32_t index);
   void (*ThrowNullPointerException)(unsigned dex_pc);
 
   //----------------------------------------------------------------------------
   // Alloc
   //----------------------------------------------------------------------------
-  Object* (*AllocArray)(uint32_t type_idx, Method* referrer,
+  Object* (*AllocArray)(uint32_t type_idx, AbstractMethod* referrer,
                         uint32_t length, Thread* thread);
 
-  Object* (*AllocArrayWithAccessCheck)(uint32_t type_idx, Method* referrer,
+  Object* (*AllocArrayWithAccessCheck)(uint32_t type_idx, AbstractMethod* referrer,
                                        uint32_t length, Thread* thread);
 
-  Object* (*CheckAndAllocArray)(uint32_t type_idx, Method* referrer,
+  Object* (*CheckAndAllocArray)(uint32_t type_idx, AbstractMethod* referrer,
                                 uint32_t length, Thread* thread);
 
   Object* (*CheckAndAllocArrayWithAccessCheck)(uint32_t type_idx,
-                                               Method* referrer,
+                                               AbstractMethod* referrer,
                                                uint32_t length,
                                                Thread* thread);
 
   //----------------------------------------------------------------------------
   // DexCache
   //----------------------------------------------------------------------------
-  Object* (*ResolveString)(Method* referrer, uint32_t string_idx);
+  Object* (*ResolveString)(AbstractMethod* referrer, uint32_t string_idx);
 
   //----------------------------------------------------------------------------
   // Field
   //----------------------------------------------------------------------------
-  Object* (*GetObjectStatic)(uint32_t field_idx, Method* referrer);
+  Object* (*GetObjectStatic)(uint32_t field_idx, AbstractMethod* referrer);
 
   //----------------------------------------------------------------------------
   // Cast
diff --git a/src/greenland/x86/x86_invoke_stub_compiler.cc b/src/greenland/x86/x86_invoke_stub_compiler.cc
index 18a7765..872a9da 100644
--- a/src/greenland/x86/x86_invoke_stub_compiler.cc
+++ b/src/greenland/x86/x86_invoke_stub_compiler.cc
@@ -128,7 +128,7 @@
     }
   }
 
-  __ call(Address(EAX, Method::GetCodeOffset()));  // Call code off of method
+  __ call(Address(EAX, AbstractMethod::GetCodeOffset()));  // Call code off of method
 
   // Pop arguments up to EBX and the return address.
   __ addl(ESP, Immediate(frame_size + pad_size - (2 * kPointerSize)));
diff --git a/src/image_writer.cc b/src/image_writer.cc
index 4eec311..2ec47ec 100644
--- a/src/image_writer.cc
+++ b/src/image_writer.cc
@@ -235,7 +235,7 @@
     class_linker->RemoveClass((*it).c_str(), NULL);
   }
 
-  Method* resolution_method = runtime->GetResolutionMethod();
+  AbstractMethod* resolution_method = runtime->GetResolutionMethod();
   typedef Set::const_iterator CacheIt;  // TODO: C++0x auto
   for (CacheIt it = dex_caches_.begin(), end = dex_caches_.end(); it != end; ++it) {
     DexCache* dex_cache = *it;
@@ -247,7 +247,7 @@
       }
     }
     for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) {
-      Method* method = dex_cache->GetResolvedMethod(i);
+      AbstractMethod* method = dex_cache->GetResolvedMethod(i);
       if (method != NULL && !IsImageClass(method->GetDeclaringClass())) {
         dex_cache->SetResolvedMethod(i, resolution_method);
       }
@@ -398,12 +398,15 @@
     heap->FlushAllocStack();
   }
 
-  // TODO: Image spaces only?
   {
-    for (SpaceVec::const_iterator cur = spaces.begin(); cur != spaces.end(); ++cur) {
-      (*cur)->GetLiveBitmap()->InOrderWalk(CalculateNewObjectOffsetsCallback, this);
+    // TODO: Image spaces only?
+    // TODO: Add InOrderWalk to heap bitmap.
+    const char* old = Thread::Current()->StartAssertNoThreadSuspension("ImageWriter");
+    for (SpaceVec::const_iterator it = spaces.begin(); it != spaces.end(); ++it) {
+      (*it)->GetLiveBitmap()->InOrderWalk(CalculateNewObjectOffsetsCallback, this);
       DCHECK_LT(image_end_, image_->Size());
     }
+    Thread::Current()->EndAssertNoThreadSuspension(old);
   }
 
   // Note that image_top_ is left at end of used space
@@ -421,6 +424,7 @@
 
 void ImageWriter::CopyAndFixupObjects()
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  const char* old_cause = Thread::Current()->StartAssertNoThreadSuspension("ImageWriter");
   Heap* heap = Runtime::Current()->GetHeap();
   // TODO: heap validation can't handle this fix up pass
   heap->DisableObjectValidation();
@@ -428,6 +432,7 @@
   ReaderMutexLock mu(*Locks::heap_bitmap_lock_);
   heap->FlushAllocStack();
   heap->GetLiveBitmap()->Walk(CopyAndFixupObjectsCallback, this);
+  Thread::Current()->EndAssertNoThreadSuspension(old_cause);
 }
 
 void ImageWriter::CopyAndFixupObjectsCallback(Object* object, void* arg) {
@@ -461,7 +466,7 @@
   } else if (orig->IsObjectArray()) {
     FixupObjectArray(orig->AsObjectArray<Object>(), down_cast<ObjectArray<Object>*>(copy));
   } else if (orig->IsMethod()) {
-    FixupMethod(orig->AsMethod(), down_cast<Method*>(copy));
+    FixupMethod(orig->AsMethod(), down_cast<AbstractMethod*>(copy));
   } else {
     FixupInstanceFields(orig, copy);
   }
@@ -472,7 +477,7 @@
   FixupStaticFields(orig, copy);
 }
 
-void ImageWriter::FixupMethod(const Method* orig, Method* copy) {
+void ImageWriter::FixupMethod(const AbstractMethod* orig, AbstractMethod* copy) {
   FixupInstanceFields(orig, copy);
 
   // OatWriter replaces the code_ and invoke_stub_ with offset values.
@@ -481,7 +486,7 @@
   // Every type of method can have an invoke stub
   uint32_t invoke_stub_offset = orig->GetOatInvokeStubOffset();
   const byte* invoke_stub = GetOatAddress(invoke_stub_offset);
-  copy->invoke_stub_ = reinterpret_cast<Method::InvokeStub*>(const_cast<byte*>(invoke_stub));
+  copy->invoke_stub_ = reinterpret_cast<AbstractMethod::InvokeStub*>(const_cast<byte*>(invoke_stub));
 
   if (orig->IsAbstract()) {
     // Abstract methods are pointed to a stub that will throw AbstractMethodError if they are called
@@ -603,12 +608,12 @@
   }
 }
 
-static Method* GetReferrerMethod(const Compiler::PatchInformation* patch)
+static AbstractMethod* GetReferrerMethod(const Compiler::PatchInformation* patch)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedObjectAccessUnchecked soa(Thread::Current());
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   DexCache* dex_cache = class_linker->FindDexCache(patch->GetDexFile());
-  Method* method = class_linker->ResolveMethod(patch->GetDexFile(),
+  AbstractMethod* method = class_linker->ResolveMethod(patch->GetDexFile(),
                                                patch->GetReferrerMethodIdx(),
                                                dex_cache,
                                                NULL,
@@ -625,11 +630,11 @@
   return method;
 }
 
-static Method* GetTargetMethod(const Compiler::PatchInformation* patch)
+static AbstractMethod* GetTargetMethod(const Compiler::PatchInformation* patch)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   DexCache* dex_cache = class_linker->FindDexCache(patch->GetDexFile());
-  Method* method = class_linker->ResolveMethod(patch->GetDexFile(),
+  AbstractMethod* method = class_linker->ResolveMethod(patch->GetDexFile(),
                                                patch->GetTargetMethodIdx(),
                                                dex_cache,
                                                NULL,
@@ -652,7 +657,7 @@
   const std::vector<const Compiler::PatchInformation*>& code_to_patch = compiler.GetCodeToPatch();
   for (size_t i = 0; i < code_to_patch.size(); i++) {
     const Compiler::PatchInformation* patch = code_to_patch[i];
-    Method* target = GetTargetMethod(patch);
+    AbstractMethod* target = GetTargetMethod(patch);
     uint32_t code = reinterpret_cast<uint32_t>(class_linker->GetOatCodeFor(target));
     uint32_t code_base = reinterpret_cast<uint32_t>(&oat_file_->GetOatHeader());
     uint32_t code_offset = code - code_base;
@@ -663,14 +668,14 @@
       = compiler.GetMethodsToPatch();
   for (size_t i = 0; i < methods_to_patch.size(); i++) {
     const Compiler::PatchInformation* patch = methods_to_patch[i];
-    Method* target = GetTargetMethod(patch);
+    AbstractMethod* target = GetTargetMethod(patch);
     SetPatchLocation(patch, reinterpret_cast<uint32_t>(GetImageAddress(target)));
   }
 }
 
 void ImageWriter::SetPatchLocation(const Compiler::PatchInformation* patch, uint32_t value) {
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  Method* method = GetReferrerMethod(patch);
+  AbstractMethod* method = GetReferrerMethod(patch);
   // Goodbye const, we are about to modify some code.
   void* code = const_cast<void*>(class_linker->GetOatCodeFor(method));
   // TODO: make this Thumb2 specific
diff --git a/src/image_writer.h b/src/image_writer.h
index 8e8d106..5a8da1b 100644
--- a/src/image_writer.h
+++ b/src/image_writer.h
@@ -140,7 +140,7 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void FixupClass(const Class* orig, Class* copy)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  void FixupMethod(const Method* orig, Method* copy)
+  void FixupMethod(const AbstractMethod* orig, AbstractMethod* copy)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void FixupObject(const Object* orig, Object* copy)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/src/jdwp/jdwp.h b/src/jdwp/jdwp.h
index 54e5cc7..3186006 100644
--- a/src/jdwp/jdwp.h
+++ b/src/jdwp/jdwp.h
@@ -31,7 +31,7 @@
 
 namespace art {
 
-class Method;
+class AbstractMethod;
 class Thread;
 
 namespace JDWP {
diff --git a/src/jni_compiler_test.cc b/src/jni_compiler_test.cc
index e0320b3..31b14c9 100644
--- a/src/jni_compiler_test.cc
+++ b/src/jni_compiler_test.cc
@@ -44,7 +44,7 @@
     ScopedObjectAccess soa(Thread::Current());
     // Compile the native method before starting the runtime
     Class* c = class_linker_->FindClass("LMyClassNatives;", soa.Decode<ClassLoader*>(class_loader));
-    Method* method;
+    AbstractMethod* method;
     if (direct) {
       method = c->FindDirectMethod(method_name, method_sig);
     } else {
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 6230a66..8c67fb4 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -93,7 +93,7 @@
 
 class ArgArray {
  public:
-  explicit ArgArray(Method* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  explicit ArgArray(AbstractMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     MethodHelper mh(method);
     shorty_ = mh.GetShorty();
     shorty_len_ = mh.GetShortyLength();
@@ -200,7 +200,7 @@
   return reinterpret_cast<jweak>(ref);
 }
 
-static void CheckMethodArguments(Method* m, JValue* args)
+static void CheckMethodArguments(AbstractMethod* m, JValue* args)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   MethodHelper mh(m);
   ObjectArray<Class>* parameter_types = mh.GetParameterTypes();
@@ -226,7 +226,7 @@
 }
 
 static JValue InvokeWithArgArray(const ScopedObjectAccess& soa, Object* receiver,
-                                 Method* method, JValue* args)
+                                 AbstractMethod* method, JValue* args)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   if (UNLIKELY(soa.Env()->check_jni)) {
     CheckMethodArguments(method, args);
@@ -240,13 +240,13 @@
                                 jmethodID mid, va_list args)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   Object* receiver = soa.Decode<Object*>(obj);
-  Method* method = soa.DecodeMethod(mid);
+  AbstractMethod* method = soa.DecodeMethod(mid);
   ArgArray arg_array(method);
   arg_array.BuildArgArray(soa, args);
   return InvokeWithArgArray(soa, receiver, method, arg_array.get());
 }
 
-static Method* FindVirtualMethod(Object* receiver, Method* method)
+static AbstractMethod* FindVirtualMethod(Object* receiver, AbstractMethod* method)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   return receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(method);
 }
@@ -255,7 +255,7 @@
                                                   jobject obj, jmethodID mid, jvalue* args)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   Object* receiver = soa.Decode<Object*>(obj);
-  Method* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid));
+  AbstractMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid));
   ArgArray arg_array(method);
   arg_array.BuildArgArray(soa, args);
   return InvokeWithArgArray(soa, receiver, method, arg_array.get());
@@ -265,7 +265,7 @@
                                                   jobject obj, jmethodID mid, va_list args)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   Object* receiver = soa.Decode<Object*>(obj);
-  Method* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid));
+  AbstractMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid));
   ArgArray arg_array(method);
   arg_array.BuildArgArray(soa, args);
   return InvokeWithArgArray(soa, receiver, method, arg_array.get());
@@ -310,7 +310,7 @@
     return NULL;
   }
 
-  Method* method = NULL;
+  AbstractMethod* method = NULL;
   if (is_static) {
     method = c->FindDirectMethod(name, sig);
   } else {
@@ -332,7 +332,7 @@
 
 static ClassLoader* GetClassLoader(Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  Method* method = self->GetCurrentMethod();
+  AbstractMethod* method = self->GetCurrentMethod();
   if (method == NULL || PrettyMethod(method, false) == "java.lang.Runtime.nativeLoad") {
     return self->GetClassLoaderOverride();
   }
@@ -614,7 +614,7 @@
   }
 
   // See section 11.3 "Linking Native Methods" of the JNI spec.
-  void* FindNativeMethod(const Method* m, std::string& detail)
+  void* FindNativeMethod(const AbstractMethod* m, std::string& detail)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     std::string jni_short_name(JniShortName(m));
     std::string jni_long_name(JniLongName(m));
@@ -652,13 +652,13 @@
 JValue InvokeWithJValues(const ScopedObjectAccess& soa, jobject obj, jmethodID mid,
                          jvalue* args) {
   Object* receiver = soa.Decode<Object*>(obj);
-  Method* method = soa.DecodeMethod(mid);
+  AbstractMethod* method = soa.DecodeMethod(mid);
   ArgArray arg_array(method);
   arg_array.BuildArgArray(soa, args);
   return InvokeWithArgArray(soa, receiver, method, arg_array.get());
 }
 
-JValue InvokeWithJValues(const ScopedObjectAccess& soa, Object* receiver, Method* m,
+JValue InvokeWithJValues(const ScopedObjectAccess& soa, Object* receiver, AbstractMethod* m,
                          JValue* args)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   return InvokeWithArgArray(soa, receiver, m, args);
@@ -692,7 +692,7 @@
 
   static jmethodID FromReflectedMethod(JNIEnv* env, jobject java_method) {
     ScopedObjectAccess soa(env);
-    Method* method = soa.Decode<Method*>(java_method);
+    AbstractMethod* method = soa.Decode<AbstractMethod*>(java_method);
     return soa.EncodeMethod(method);
   }
 
@@ -704,7 +704,7 @@
 
   static jobject ToReflectedMethod(JNIEnv* env, jclass, jmethodID mid, jboolean) {
     ScopedObjectAccess soa(env);
-    Method* method = soa.DecodeMethod(mid);
+    AbstractMethod* method = soa.DecodeMethod(mid);
     return soa.AddLocalReference<jobject>(method);
   }
 
@@ -2125,7 +2125,7 @@
         ++sig;
       }
 
-      Method* m = c->FindDirectMethod(name, sig);
+      AbstractMethod* m = c->FindDirectMethod(name, sig);
       if (m == NULL) {
         m = c->FindVirtualMethod(name, sig);
       }
@@ -2153,13 +2153,13 @@
     VLOG(jni) << "[Unregistering JNI native methods for " << PrettyClass(c) << "]";
 
     for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
-      Method* m = c->GetDirectMethod(i);
+      AbstractMethod* m = c->GetDirectMethod(i);
       if (m->IsNative()) {
         m->UnregisterNative(soa.Self());
       }
     }
     for (size_t i = 0; i < c->NumVirtualMethods(); ++i) {
-      Method* m = c->GetVirtualMethod(i);
+      AbstractMethod* m = c->GetVirtualMethod(i);
       if (m->IsNative()) {
         m->UnregisterNative(soa.Self());
       }
@@ -2939,7 +2939,7 @@
   return result;
 }
 
-void* JavaVMExt::FindCodeForNativeMethod(Method* m) {
+void* JavaVMExt::FindCodeForNativeMethod(AbstractMethod* m) {
   CHECK(m->IsNative());
 
   Class* c = m->GetDeclaringClass();
diff --git a/src/jni_internal.h b/src/jni_internal.h
index 6833c2a..c683464 100644
--- a/src/jni_internal.h
+++ b/src/jni_internal.h
@@ -42,7 +42,7 @@
 class Field;
 union JValue;
 class Libraries;
-class Method;
+class AbstractMethod;
 class ScopedObjectAccess;
 class Thread;
 
@@ -55,7 +55,7 @@
 size_t NumArgArrayBytes(const char* shorty, uint32_t shorty_len);
 JValue InvokeWithJValues(const ScopedObjectAccess&, jobject obj, jmethodID mid, jvalue* args)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-JValue InvokeWithJValues(const ScopedObjectAccess&, Object* receiver, Method* m, JValue* args)
+JValue InvokeWithJValues(const ScopedObjectAccess&, Object* receiver, AbstractMethod* m, JValue* args)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 int ThrowNewException(JNIEnv* env, jclass exception_class, const char* msg, jobject cause);
@@ -77,7 +77,7 @@
    * Returns a pointer to the code for the native method 'm', found
    * using dlsym(3) on every native library that's been loaded so far.
    */
-  void* FindCodeForNativeMethod(Method* m)
+  void* FindCodeForNativeMethod(AbstractMethod* m)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void DumpForSigQuit(std::ostream& os);
diff --git a/src/jni_internal_test.cc b/src/jni_internal_test.cc
index 5db258d..329b51c 100644
--- a/src/jni_internal_test.cc
+++ b/src/jni_internal_test.cc
@@ -68,7 +68,7 @@
     CommonTest::TearDown();
   }
 
-  Method::InvokeStub* DoCompile(Method*& method, Object*& receiver, bool is_static,
+  AbstractMethod::InvokeStub* DoCompile(AbstractMethod*& method, Object*& receiver, bool is_static,
                                 const char* method_name, const char* method_signature)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     const char* class_name = is_static ? "StaticLeafMethods" : "NonStaticLeafMethods";
@@ -91,24 +91,24 @@
 
     receiver = (is_static ? NULL : c->AllocObject());
 
-    Method::InvokeStub* stub = method->GetInvokeStub();
+    AbstractMethod::InvokeStub* stub = method->GetInvokeStub();
     CHECK(stub != NULL);
 
     return stub;
   }
 
   void InvokeNopMethod(bool is_static) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    Method* method;
+    AbstractMethod* method;
     Object* receiver;
-    Method::InvokeStub* stub = DoCompile(method, receiver, is_static, "nop", "()V");
+    AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "nop", "()V");
     (*stub)(method, receiver, Thread::Current(), NULL, NULL);
   }
 
   void InvokeIdentityByteMethod(bool is_static)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    Method* method;
+    AbstractMethod* method;
     Object* receiver;
-    Method::InvokeStub* stub = DoCompile(method, receiver, is_static, "identity", "(B)B");
+    AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "identity", "(B)B");
 
     JValue args[1];
     JValue result;
@@ -136,9 +136,9 @@
 
   void InvokeIdentityIntMethod(bool is_static)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    Method* method;
+    AbstractMethod* method;
     Object* receiver;
-    Method::InvokeStub* stub = DoCompile(method, receiver, is_static, "identity", "(I)I");
+    AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "identity", "(I)I");
 
     JValue args[1];
     JValue result;
@@ -166,9 +166,9 @@
 
   void InvokeIdentityDoubleMethod(bool is_static)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    Method* method;
+    AbstractMethod* method;
     Object* receiver;
-    Method::InvokeStub* stub = DoCompile(method, receiver, is_static, "identity", "(D)D");
+    AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "identity", "(D)D");
 
     JValue args[1];
     JValue result;
@@ -196,9 +196,9 @@
 
   void InvokeSumIntIntMethod(bool is_static)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    Method* method;
+    AbstractMethod* method;
     Object* receiver;
-    Method::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(II)I");
+    AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(II)I");
 
     JValue result;
     result.SetI(-1);
@@ -235,9 +235,9 @@
 
   void InvokeSumIntIntIntMethod(bool is_static)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    Method* method;
+    AbstractMethod* method;
     Object* receiver;
-    Method::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(III)I");
+    AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(III)I");
 
     JValue result;
     result.SetI(-1);
@@ -279,9 +279,9 @@
 
   void InvokeSumIntIntIntIntMethod(bool is_static)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    Method* method;
+    AbstractMethod* method;
     Object* receiver;
-    Method::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(IIII)I");
+    AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(IIII)I");
 
     JValue result;
     result.SetI(-1);
@@ -328,9 +328,9 @@
 
   void InvokeSumIntIntIntIntIntMethod(bool is_static)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    Method* method;
+    AbstractMethod* method;
     Object* receiver;
-    Method::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(IIIII)I");
+    AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(IIIII)I");
 
     JValue result;
     result.SetI(-1.0);
@@ -382,9 +382,9 @@
 
   void InvokeSumDoubleDoubleMethod(bool is_static)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    Method* method;
+    AbstractMethod* method;
     Object* receiver;
-    Method::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(DD)D");
+    AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(DD)D");
 
     JValue args[2];
     JValue result;
@@ -422,9 +422,9 @@
 
   void InvokeSumDoubleDoubleDoubleMethod(bool is_static)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    Method* method;
+    AbstractMethod* method;
     Object* receiver;
-    Method::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(DDD)D");
+    AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(DDD)D");
 
     JValue args[3];
     JValue result;
@@ -453,9 +453,9 @@
 
   void InvokeSumDoubleDoubleDoubleDoubleMethod(bool is_static)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    Method* method;
+    AbstractMethod* method;
     Object* receiver;
-    Method::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(DDDD)D");
+    AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(DDDD)D");
 
     JValue args[4];
     JValue result;
@@ -487,9 +487,9 @@
 
   void InvokeSumDoubleDoubleDoubleDoubleDoubleMethod(bool is_static)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    Method* method;
+    AbstractMethod* method;
     Object* receiver;
-    Method::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(DDDDD)D");
+    AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(DDDDD)D");
 
     JValue args[5];
     JValue result;
@@ -1388,10 +1388,10 @@
   Class* klass = class_linker_->FindClass("LMain;", class_loader.get());
   ASSERT_TRUE(klass != NULL);
 
-  Method* method = klass->FindDirectMethod("main", "([Ljava/lang/String;)V");
+  AbstractMethod* method = klass->FindDirectMethod("main", "([Ljava/lang/String;)V");
   ASSERT_TRUE(method != NULL);
 
-  Method::InvokeStub* stub = method->GetInvokeStub();
+  AbstractMethod::InvokeStub* stub = method->GetInvokeStub();
 
   JValue args[1];
   args[0].SetL(NULL);
diff --git a/src/monitor.cc b/src/monitor.cc
index 6b7fbf1..6a18a90 100644
--- a/src/monitor.cc
+++ b/src/monitor.cc
@@ -205,7 +205,7 @@
     uint64_t waitStart = 0;
     uint64_t waitEnd = 0;
     uint32_t wait_threshold = lock_profiling_threshold_;
-    const Method* current_locking_method = NULL;
+    const AbstractMethod* current_locking_method = NULL;
     uint32_t current_locking_dex_pc = 0;
     {
       ScopedThreadStateChange tsc(self, kBlocked);
@@ -461,7 +461,7 @@
   int prev_lock_count = lock_count_;
   lock_count_ = 0;
   owner_ = NULL;
-  const Method* saved_method = locking_method_;
+  const AbstractMethod* saved_method = locking_method_;
   locking_method_ = NULL;
   uintptr_t saved_dex_pc = locking_dex_pc_;
   locking_dex_pc_ = 0;
@@ -918,7 +918,7 @@
 }
 
 void Monitor::DescribeLocks(std::ostream& os, StackVisitor* stack_visitor) {
-  Method* m = stack_visitor->GetMethod();
+  AbstractMethod* m = stack_visitor->GetMethod();
   CHECK(m != NULL);
 
   // Native methods are an easy special case.
@@ -982,7 +982,7 @@
   }
 }
 
-void Monitor::TranslateLocation(const Method* method, uint32_t dex_pc,
+void Monitor::TranslateLocation(const AbstractMethod* method, uint32_t dex_pc,
                                 const char*& source_file, uint32_t& line_number) const {
   // If method is null, location is unknown
   if (method == NULL) {
diff --git a/src/monitor.h b/src/monitor.h
index de70803..4a62728 100644
--- a/src/monitor.h
+++ b/src/monitor.h
@@ -56,7 +56,7 @@
 #define LW_LOCK_OWNER_SHIFT 3
 #define LW_LOCK_OWNER(x) (((x) >> LW_LOCK_OWNER_SHIFT) & LW_LOCK_OWNER_MASK)
 
-class Method;
+class AbstractMethod;
 class Object;
 class Thread;
 class StackVisitor;
@@ -132,7 +132,7 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Translates the provided method and pc into its declaring class' source file and line number.
-  void TranslateLocation(const Method* method, uint32_t pc,
+  void TranslateLocation(const AbstractMethod* method, uint32_t pc,
                          const char*& source_file, uint32_t& line_number) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -156,7 +156,7 @@
   // Method and dex pc where the lock owner acquired the lock, used when lock
   // sampling is enabled. locking_method_ may be null if the lock is currently
   // unlocked, or if the lock is acquired by the system when the stack is empty.
-  const Method* locking_method_ GUARDED_BY(monitor_lock_);
+  const AbstractMethod* locking_method_ GUARDED_BY(monitor_lock_);
   uint32_t locking_dex_pc_ GUARDED_BY(monitor_lock_);
 
   friend class MonitorList;
diff --git a/src/monitor_android.cc b/src/monitor_android.cc
index ce42ee7..6e22237 100644
--- a/src/monitor_android.cc
+++ b/src/monitor_android.cc
@@ -79,7 +79,7 @@
 
   // Emit the source code file name, <= 37 bytes.
   uintptr_t pc;
-  Method* m = self->GetCurrentMethod(&pc);
+  AbstractMethod* m = self->GetCurrentMethod(&pc);
   const char* filename;
   uint32_t line_number;
   TranslateLocation(m, pc, filename, line_number);
diff --git a/src/native/java_lang_Class.cc b/src/native/java_lang_Class.cc
index 68fc97e..c023b7e 100644
--- a/src/native/java_lang_Class.cc
+++ b/src/native/java_lang_Class.cc
@@ -105,7 +105,7 @@
 };
 #define ToArray(a, b, c) WorkAroundGccAnnotalysisBug::ToArray(a, b, c)
 
-static bool IsVisibleConstructor(Method* m, bool public_only) {
+static bool IsVisibleConstructor(AbstractMethod* m, bool public_only) {
   if (public_only && !m->IsPublic()) {
     return false;
   }
@@ -118,9 +118,9 @@
 static jobjectArray Class_getDeclaredConstructors(JNIEnv* env, jclass javaClass, jboolean publicOnly) {
   ScopedObjectAccess soa(env);
   Class* c = DecodeClass(soa, javaClass);
-  std::vector<Method*> constructors;
+  std::vector<AbstractMethod*> constructors; // TODO: Use Constructor instead of AbstractMethod
   for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
-    Method* m = c->GetDirectMethod(i);
+    AbstractMethod* m = c->GetDirectMethod(i);
     if (IsVisibleConstructor(m, publicOnly)) {
       constructors.push_back(m);
     }
@@ -173,7 +173,7 @@
   return ToArray(soa, "java/lang/reflect/Field", fields);
 }
 
-static bool IsVisibleMethod(Method* m, bool public_only) {
+static bool IsVisibleMethod(AbstractMethod* m, bool public_only) {
   if (public_only && !m->IsPublic()) {
     return false;
   }
@@ -193,10 +193,10 @@
     return NULL;
   }
 
-  std::vector<Method*> methods;
+  std::vector<AbstractMethod*> methods;
   MethodHelper mh;
   for (size_t i = 0; i < c->NumVirtualMethods(); ++i) {
-    Method* m = c->GetVirtualMethod(i);
+    AbstractMethod* m = c->GetVirtualMethod(i);
     mh.ChangeMethod(m);
     if (IsVisibleMethod(m, publicOnly)) {
       if (mh.GetReturnType() == NULL || mh.GetParameterTypes() == NULL) {
@@ -210,7 +210,7 @@
     }
   }
   for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
-    Method* m = c->GetDirectMethod(i);
+    AbstractMethod* m = c->GetDirectMethod(i);
     mh.ChangeMethod(m);
     if (IsVisibleMethod(m, publicOnly)) {
       if (mh.GetReturnType() == NULL || mh.GetParameterTypes() == NULL) {
@@ -260,16 +260,17 @@
   return true;
 }
 
-static Method* FindConstructorOrMethodInArray(ObjectArray<Method>* methods, const std::string& name,
-                                              ObjectArray<Class>* arg_array)
+static AbstractMethod* FindConstructorOrMethodInArray(ObjectArray<AbstractMethod>* methods,
+                                                      const std::string& name,
+                                                      ObjectArray<Class>* arg_array)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   if (methods == NULL) {
     return NULL;
   }
-  Method* result = NULL;
+  AbstractMethod* result = NULL;
   MethodHelper mh;
   for (int32_t i = 0; i < methods->GetLength(); ++i) {
-    Method* method = methods->Get(i);
+    AbstractMethod* method = methods->Get(i);
     mh.ChangeMethod(method);
     if (method->IsMiranda() || !MethodMatches(&mh, name, arg_array)) {
       continue;
@@ -295,7 +296,7 @@
   std::string name(soa.Decode<String*>(javaName)->ToModifiedUtf8());
   ObjectArray<Class>* arg_array = soa.Decode<ObjectArray<Class>*>(javaArgs);
 
-  Method* m = FindConstructorOrMethodInArray(c->GetDirectMethods(), name, arg_array);
+  AbstractMethod* m = FindConstructorOrMethodInArray(c->GetDirectMethods(), name, arg_array);
   if (m == NULL) {
     m = FindConstructorOrMethodInArray(c->GetVirtualMethods(), name, arg_array);
   }
@@ -375,7 +376,7 @@
     return NULL;
   }
 
-  Method* init = c->FindDeclaredDirectMethod("<init>", "()V");
+  AbstractMethod* init = c->FindDeclaredDirectMethod("<init>", "()V");
   if (init == NULL) {
     soa.Self()->ThrowNewExceptionF("Ljava/lang/InstantiationException;",
         "Class %s has no default <init>()V constructor", PrettyDescriptor(ClassHelper(c).GetDescriptor()).c_str());
diff --git a/src/native/java_lang_reflect_Constructor.cc b/src/native/java_lang_reflect_Constructor.cc
index a6bd450..44b459d 100644
--- a/src/native/java_lang_reflect_Constructor.cc
+++ b/src/native/java_lang_reflect_Constructor.cc
@@ -32,7 +32,7 @@
  */
 static jobject Constructor_newInstance(JNIEnv* env, jobject javaMethod, jobjectArray javaArgs) {
   ScopedObjectAccess soa(env);
-  Method* m = soa.Decode<Object*>(javaMethod)->AsMethod();
+  AbstractMethod* m = soa.Decode<Object*>(javaMethod)->AsMethod();
   Class* c = m->GetDeclaringClass();
   if (c->IsAbstract()) {
     soa.Self()->ThrowNewExceptionF("Ljava/lang/InstantiationException;",
diff --git a/src/native/java_lang_reflect_Method.cc b/src/native/java_lang_reflect_Method.cc
index 2a6ee50..63a277b 100644
--- a/src/native/java_lang_reflect_Method.cc
+++ b/src/native/java_lang_reflect_Method.cc
@@ -30,7 +30,7 @@
 
 static jobject Method_getExceptionTypesNative(JNIEnv* env, jobject javaMethod) {
   ScopedObjectAccess soa(env);
-  Method* proxy_method = soa.Decode<Object*>(javaMethod)->AsMethod();
+  AbstractMethod* proxy_method = soa.Decode<Object*>(javaMethod)->AsMethod();
   CHECK(proxy_method->GetDeclaringClass()->IsProxyClass());
   SynthesizedProxyClass* proxy_class =
       down_cast<SynthesizedProxyClass*>(proxy_method->GetDeclaringClass());
@@ -49,7 +49,7 @@
 
 static jobject Method_findOverriddenMethodNative(JNIEnv* env, jobject javaMethod) {
   ScopedObjectAccess soa(env);
-  Method* method = soa.Decode<Object*>(javaMethod)->AsMethod();
+  AbstractMethod* method = soa.Decode<Object*>(javaMethod)->AsMethod();
   return soa.AddLocalReference<jobject>(method->FindOverriddenMethod());
 }
 
diff --git a/src/native/java_lang_reflect_Proxy.cc b/src/native/java_lang_reflect_Proxy.cc
index 81e3f169..a567268 100644
--- a/src/native/java_lang_reflect_Proxy.cc
+++ b/src/native/java_lang_reflect_Proxy.cc
@@ -27,7 +27,7 @@
   String* name = soa.Decode<String*>(javaName);
   ObjectArray<Class>* interfaces = soa.Decode<ObjectArray<Class>*>(javaInterfaces);
   ClassLoader* loader = soa.Decode<ClassLoader*>(javaLoader);
-  ObjectArray<Method>* methods = soa.Decode<ObjectArray<Method>*>(javaMethods);
+  ObjectArray<AbstractMethod>* methods = soa.Decode<ObjectArray<AbstractMethod>*>(javaMethods);
   ObjectArray<ObjectArray<Class> >* throws = soa.Decode<ObjectArray<ObjectArray<Class> >*>(javaThrows);
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   Class* result = class_linker->CreateProxyClass(name, interfaces, loader, methods, throws);
diff --git a/src/nth_caller_visitor.h b/src/nth_caller_visitor.h
index 0f29ae7..6b3894e 100644
--- a/src/nth_caller_visitor.h
+++ b/src/nth_caller_visitor.h
@@ -38,7 +38,7 @@
 
   size_t n;
   size_t count;
-  Method* caller;
+  AbstractMethod* caller;
 };
 
 }  // namespace art
diff --git a/src/oat/jni/arm/jni_internal_arm.cc b/src/oat/jni/arm/jni_internal_arm.cc
index bbbe6ad..5220669 100644
--- a/src/oat/jni/arm/jni_internal_arm.cc
+++ b/src/oat/jni/arm/jni_internal_arm.cc
@@ -129,7 +129,7 @@
   }
 
   // Load the code pointer we are about to call.
-  __ LoadFromOffset(kLoadWord, IP, R0, Method::GetCodeOffset().Int32Value());
+  __ LoadFromOffset(kLoadWord, IP, R0, AbstractMethod::GetCodeOffset().Int32Value());
 
   // Do the call.
   __ blx(IP);
diff --git a/src/oat/jni/jni_compiler.cc b/src/oat/jni/jni_compiler.cc
index dc1bfc7..7b710c5 100644
--- a/src/oat/jni/jni_compiler.cc
+++ b/src/oat/jni/jni_compiler.cc
@@ -118,7 +118,7 @@
     // Check sirt offset is within frame
     CHECK_LT(sirt_offset.Uint32Value(), frame_size);
     __ LoadRef(main_jni_conv->InterproceduralScratchRegister(),
-               mr_conv->MethodRegister(), Method::DeclaringClassOffset());
+               mr_conv->MethodRegister(), AbstractMethod::DeclaringClassOffset());
     __ VerifyObject(main_jni_conv->InterproceduralScratchRegister(), false);
     __ StoreRef(sirt_offset, main_jni_conv->InterproceduralScratchRegister());
     main_jni_conv->Next();  // in SIRT so move to next argument
@@ -269,7 +269,7 @@
   }
 
   // 9. Plant call to native code associated with method.
-  __ Call(main_jni_conv->MethodStackOffset(), Method::NativeMethodOffset(),
+  __ Call(main_jni_conv->MethodStackOffset(), AbstractMethod::NativeMethodOffset(),
           mr_conv->InterproceduralScratchRegister());
 
   // 10. Fix differences in result widths.
diff --git a/src/oat/jni/mips/jni_internal_mips.cc b/src/oat/jni/mips/jni_internal_mips.cc
index 0a2ab1d..ea2d7a1 100644
--- a/src/oat/jni/mips/jni_internal_mips.cc
+++ b/src/oat/jni/mips/jni_internal_mips.cc
@@ -123,7 +123,7 @@
   }
 
   // Load the code pointer we are about to call.
-  __ LoadFromOffset(kLoadWord, T9, A0, Method::GetCodeOffset().Int32Value());
+  __ LoadFromOffset(kLoadWord, T9, A0, AbstractMethod::GetCodeOffset().Int32Value());
 
   // Do the call.
   __ Jalr(T9);
diff --git a/src/oat/jni/x86/jni_internal_x86.cc b/src/oat/jni/x86/jni_internal_x86.cc
index 498ca43..a9d4004 100644
--- a/src/oat/jni/x86/jni_internal_x86.cc
+++ b/src/oat/jni/x86/jni_internal_x86.cc
@@ -125,7 +125,7 @@
     }
   }
 
-  __ call(Address(EAX, Method::GetCodeOffset()));  // Call code off of method
+  __ call(Address(EAX, AbstractMethod::GetCodeOffset()));  // Call code off of method
 
   // Pop arguments up to EBX and the return address.
   __ addl(ESP, Immediate(frame_size + pad_size - (2 * kPointerSize)));
diff --git a/src/oat/runtime/arm/context_arm.cc b/src/oat/runtime/arm/context_arm.cc
index 2959ef6..057f41e 100644
--- a/src/oat/runtime/arm/context_arm.cc
+++ b/src/oat/runtime/arm/context_arm.cc
@@ -34,7 +34,7 @@
 }
 
 void ArmContext::FillCalleeSaves(const StackVisitor& fr) {
-  Method* method = fr.GetMethod();
+  AbstractMethod* method = fr.GetMethod();
   uint32_t core_spills = method->GetCoreSpillMask();
   uint32_t fp_core_spills = method->GetFpSpillMask();
   size_t spill_count = __builtin_popcount(core_spills);
diff --git a/src/oat/runtime/arm/oat_support_entrypoints_arm.cc b/src/oat/runtime/arm/oat_support_entrypoints_arm.cc
index df26e21..7981466 100644
--- a/src/oat/runtime/arm/oat_support_entrypoints_arm.cc
+++ b/src/oat/runtime/arm/oat_support_entrypoints_arm.cc
@@ -33,7 +33,7 @@
 extern "C" void art_check_cast_from_code(void*, void*);
 
 // Debug entrypoints.
-extern void DebugMe(Method* method, uint32_t info);
+extern void DebugMe(AbstractMethod* method, uint32_t info);
 extern "C" void art_update_debugger(void*, void*, int32_t, void*);
 
 // DexCache entrypoints.
@@ -122,7 +122,7 @@
 extern "C" int32_t art_string_compareto(void*, void*);
 
 // Invoke entrypoints.
-const void* UnresolvedDirectMethodTrampolineFromCode(Method*, Method**, Thread*,
+const void* UnresolvedDirectMethodTrampolineFromCode(AbstractMethod*, AbstractMethod**, Thread*,
                                                      Runtime::TrampolineType);
 extern "C" void art_invoke_direct_trampoline_with_access_check(uint32_t, void*);
 extern "C" void art_invoke_interface_trampoline(uint32_t, void*);
@@ -136,7 +136,7 @@
 extern "C" void art_test_suspend();
 
 // Throw entrypoints.
-extern void ThrowAbstractMethodErrorFromCode(Method* method, Thread* thread, Method** sp);
+extern void ThrowAbstractMethodErrorFromCode(AbstractMethod* method, Thread* thread, AbstractMethod** sp);
 extern "C" void art_deliver_exception_from_code(void*);
 extern "C" void art_throw_array_bounds_from_code(int32_t index, int32_t limit);
 extern "C" void art_throw_div_zero_from_code();
diff --git a/src/oat/runtime/arm/stub_arm.cc b/src/oat/runtime/arm/stub_arm.cc
index d3c94a8..dca6d02 100644
--- a/src/oat/runtime/arm/stub_arm.cc
+++ b/src/oat/runtime/arm/stub_arm.cc
@@ -89,7 +89,7 @@
   return resolution_trampoline.get();
 }
 
-typedef void (*ThrowAme)(Method*, Thread*);
+typedef void (*ThrowAme)(AbstractMethod*, Thread*);
 
 ByteArray* CreateAbstractMethodErrorStub() {
   UniquePtr<ArmAssembler> assembler(static_cast<ArmAssembler*>(Assembler::Create(kArm)));
diff --git a/src/oat/runtime/callee_save_frame.h b/src/oat/runtime/callee_save_frame.h
index 9288a95..28bcda6 100644
--- a/src/oat/runtime/callee_save_frame.h
+++ b/src/oat/runtime/callee_save_frame.h
@@ -21,10 +21,10 @@
 
 namespace art {
 
-class Method;
+class AbstractMethod;
 
 // Place a special frame at the TOS that will save the callee saves for the given type.
-static void  FinishCalleeSaveFrameSetup(Thread* self, Method** sp, Runtime::CalleeSaveType type)
+static void  FinishCalleeSaveFrameSetup(Thread* self, AbstractMethod** sp, Runtime::CalleeSaveType type)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   // Be aware the store below may well stomp on an incoming argument.
   Locks::mutator_lock_->AssertSharedHeld();
diff --git a/src/oat/runtime/mips/context_mips.cc b/src/oat/runtime/mips/context_mips.cc
index ded9085..1a4cb5d 100644
--- a/src/oat/runtime/mips/context_mips.cc
+++ b/src/oat/runtime/mips/context_mips.cc
@@ -35,7 +35,7 @@
 }
 
 void MipsContext::FillCalleeSaves(const StackVisitor& fr) {
-  Method* method = fr.GetMethod();
+  AbstractMethod* method = fr.GetMethod();
   uint32_t core_spills = method->GetCoreSpillMask();
   uint32_t fp_core_spills = method->GetFpSpillMask();
   size_t spill_count = __builtin_popcount(core_spills);
diff --git a/src/oat/runtime/mips/oat_support_entrypoints_mips.cc b/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
index 71ea0ef..e39ec81 100644
--- a/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
+++ b/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
@@ -33,7 +33,7 @@
 extern "C" void art_check_cast_from_code(void*, void*);
 
 // Debug entrypoints.
-extern void DebugMe(Method* method, uint32_t info);
+extern void DebugMe(AbstractMethod* method, uint32_t info);
 extern "C" void art_update_debugger(void*, void*, int32_t, void*);
 
 // DexCache entrypoints.
@@ -121,7 +121,7 @@
 extern "C" int32_t art_string_compareto(void*, void*);
 
 // Invoke entrypoints.
-const void* UnresolvedDirectMethodTrampolineFromCode(Method*, Method**, Thread*,
+const void* UnresolvedDirectMethodTrampolineFromCode(AbstractMethod*, AbstractMethod**, Thread*,
                                                      Runtime::TrampolineType);
 extern "C" void art_invoke_direct_trampoline_with_access_check(uint32_t, void*);
 extern "C" void art_invoke_interface_trampoline(uint32_t, void*);
@@ -135,7 +135,7 @@
 extern "C" void art_test_suspend();
 
 // Throw entrypoints.
-extern void ThrowAbstractMethodErrorFromCode(Method* method, Thread* thread, Method** sp);
+extern void ThrowAbstractMethodErrorFromCode(AbstractMethod* method, Thread* thread, AbstractMethod** sp);
 extern "C" void art_deliver_exception_from_code(void*);
 extern "C" void art_throw_array_bounds_from_code(int32_t index, int32_t limit);
 extern "C" void art_throw_div_zero_from_code();
diff --git a/src/oat/runtime/mips/stub_mips.cc b/src/oat/runtime/mips/stub_mips.cc
index 301fafe..8ab3f8d 100644
--- a/src/oat/runtime/mips/stub_mips.cc
+++ b/src/oat/runtime/mips/stub_mips.cc
@@ -125,7 +125,7 @@
   return resolution_trampoline.get();
 }
 
-typedef void (*ThrowAme)(Method*, Thread*);
+typedef void (*ThrowAme)(AbstractMethod*, Thread*);
 
 ByteArray* CreateAbstractMethodErrorStub() {
   UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips)));
diff --git a/src/oat/runtime/oat_support_entrypoints.h b/src/oat/runtime/oat_support_entrypoints.h
index a069522..ab35450 100644
--- a/src/oat/runtime/oat_support_entrypoints.h
+++ b/src/oat/runtime/oat_support_entrypoints.h
@@ -27,7 +27,7 @@
 
 class Class;
 class DvmDex;
-class Method;
+class AbstractMethod;
 class Thread;
 
 struct PACKED EntryPoints {
@@ -45,7 +45,7 @@
   void (*pCheckCastFromCode)(void*, void*);
 
   // Debug
-  void (*pDebugMe)(Method*, uint32_t);
+  void (*pDebugMe)(AbstractMethod*, uint32_t);
   void (*pUpdateDebuggerFromCode)(void*, void*, int32_t, void*);
 
   // DexCache
@@ -126,7 +126,7 @@
   void* (*pMemcpy)(void*, const void*, size_t);
 
   // Invocation
-  const void* (*pUnresolvedDirectMethodTrampolineFromCode)(Method*, Method**, Thread*,
+  const void* (*pUnresolvedDirectMethodTrampolineFromCode)(AbstractMethod*, AbstractMethod**, Thread*,
                                                            Runtime::TrampolineType);
   void (*pInvokeDirectTrampolineWithAccessCheck)(uint32_t, void*);
   void (*pInvokeInterfaceTrampoline)(uint32_t, void*);
@@ -141,7 +141,7 @@
 
   // Throws
   void (*pDeliverException)(void*);
-  void (*pThrowAbstractMethodErrorFromCode)(Method* m, Thread* thread, Method** sp);
+  void (*pThrowAbstractMethodErrorFromCode)(AbstractMethod* m, Thread* thread, AbstractMethod** sp);
   void (*pThrowArrayBoundsFromCode)(int32_t, int32_t);
   void (*pThrowDivZeroFromCode)();
   void (*pThrowNoSuchMethodFromCode)(int32_t);
diff --git a/src/oat/runtime/support_alloc.cc b/src/oat/runtime/support_alloc.cc
index fb83fad..fd7fb65 100644
--- a/src/oat/runtime/support_alloc.cc
+++ b/src/oat/runtime/support_alloc.cc
@@ -19,45 +19,47 @@
 
 namespace art {
 
-extern "C" Object* artAllocObjectFromCode(uint32_t type_idx, Method* method,
-                                          Thread* self, Method** sp)
+extern "C" Object* artAllocObjectFromCode(uint32_t type_idx, AbstractMethod* method,
+                                          Thread* self, AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
   return AllocObjectFromCode(type_idx, method, self, false);
 }
 
-extern "C" Object* artAllocObjectFromCodeWithAccessCheck(uint32_t type_idx, Method* method,
-                                                         Thread* self, Method** sp)
+extern "C" Object* artAllocObjectFromCodeWithAccessCheck(uint32_t type_idx, AbstractMethod* method,
+                                                         Thread* self, AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
   return AllocObjectFromCode(type_idx, method, self, true);
 }
 
-extern "C" Array* artAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count,
-                                        Thread* self, Method** sp)
+extern "C" Array* artAllocArrayFromCode(uint32_t type_idx, AbstractMethod* method, int32_t component_count,
+                                        Thread* self, AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
   return AllocArrayFromCode(type_idx, method, component_count, false);
 }
 
-extern "C" Array* artAllocArrayFromCodeWithAccessCheck(uint32_t type_idx, Method* method,
+extern "C" Array* artAllocArrayFromCodeWithAccessCheck(uint32_t type_idx, AbstractMethod* method,
                                                        int32_t component_count,
-                                                       Thread* self, Method** sp)
+                                                       Thread* self, AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
   return AllocArrayFromCode(type_idx, method, component_count, true);
 }
 
-extern "C" Array* artCheckAndAllocArrayFromCode(uint32_t type_idx, Method* method,
-                                               int32_t component_count, Thread* self, Method** sp)
+extern "C" Array* artCheckAndAllocArrayFromCode(uint32_t type_idx, AbstractMethod* method,
+                                                int32_t component_count, Thread* self,
+                                                AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
   return CheckAndAllocArrayFromCode(type_idx, method, component_count, self, false);
 }
 
-extern "C" Array* artCheckAndAllocArrayFromCodeWithAccessCheck(uint32_t type_idx, Method* method,
+extern "C" Array* artCheckAndAllocArrayFromCodeWithAccessCheck(uint32_t type_idx,
+                                                               AbstractMethod* method,
                                                                int32_t component_count,
-                                                               Thread* self, Method** sp)
+                                                               Thread* self, AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
   return CheckAndAllocArrayFromCode(type_idx, method, component_count, self, true);
diff --git a/src/oat/runtime/support_cast.cc b/src/oat/runtime/support_cast.cc
index 45a3e60..16eddc4 100644
--- a/src/oat/runtime/support_cast.cc
+++ b/src/oat/runtime/support_cast.cc
@@ -28,7 +28,8 @@
 }
 
 // Check whether it is safe to cast one class to the other, throw exception and return -1 on failure
-extern "C" int artCheckCastFromCode(const Class* a, const Class* b, Thread* self, Method** sp)
+extern "C" int artCheckCastFromCode(const Class* a, const Class* b, Thread* self,
+                                    AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   DCHECK(a->IsClass()) << PrettyClass(a);
   DCHECK(b->IsClass()) << PrettyClass(b);
@@ -47,7 +48,7 @@
 // Tests whether 'element' can be assigned into an array of type 'array_class'.
 // Returns 0 on success and -1 if an exception is pending.
 extern "C" int artCanPutArrayElementFromCode(const Object* element, const Class* array_class,
-                                             Thread* self, Method** sp)
+                                             Thread* self, AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   DCHECK(array_class != NULL);
   // element can't be NULL as we catch this is screened in runtime_support
diff --git a/src/oat/runtime/support_debug.cc b/src/oat/runtime/support_debug.cc
index 9eaf55b..e2ca493 100644
--- a/src/oat/runtime/support_debug.cc
+++ b/src/oat/runtime/support_debug.cc
@@ -25,14 +25,14 @@
  * method entry and offset 0 within the method, we'll use an offset of -1
  * to denote method entry.
  */
-extern "C" void artUpdateDebuggerFromCode(int32_t dex_pc, Thread* self, Method** sp)
+extern "C" void artUpdateDebuggerFromCode(int32_t dex_pc, Thread* self, AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   FinishCalleeSaveFrameSetup(self, sp,  Runtime::kRefsAndArgs);
   Dbg::UpdateDebugger(dex_pc, self);
 }
 
 // Temporary debugging hook for compiler.
-extern void DebugMe(Method* method, uint32_t info)
+extern void DebugMe(AbstractMethod* method, uint32_t info)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   LOG(INFO) << "DebugMe";
   if (method != NULL) {
diff --git a/src/oat/runtime/support_dexcache.cc b/src/oat/runtime/support_dexcache.cc
index 98cce55..10c7930 100644
--- a/src/oat/runtime/support_dexcache.cc
+++ b/src/oat/runtime/support_dexcache.cc
@@ -19,8 +19,8 @@
 
 namespace art {
 
-extern "C" Class* artInitializeStaticStorageFromCode(uint32_t type_idx, const Method* referrer,
-                                                     Thread* self, Method** sp)
+extern "C" Class* artInitializeStaticStorageFromCode(uint32_t type_idx, const AbstractMethod* referrer,
+                                                     Thread* self, AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   // Called to ensure static storage base is initialized for direct static field reads and writes.
   // A class may be accessing another class' fields when it doesn't have access, as access has been
@@ -29,8 +29,8 @@
   return ResolveVerifyAndClinit(type_idx, referrer, self, true, false);
 }
 
-extern "C" Class* artInitializeTypeFromCode(uint32_t type_idx, const Method* referrer, Thread* self,
-                                            Method** sp)
+extern "C" Class* artInitializeTypeFromCode(uint32_t type_idx, const AbstractMethod* referrer,
+                                            Thread* self, AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   // Called when method->dex_cache_resolved_types_[] misses.
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
@@ -38,8 +38,9 @@
 }
 
 extern "C" Class* artInitializeTypeAndVerifyAccessFromCode(uint32_t type_idx,
-                                                           const Method* referrer, Thread* self,
-                                                           Method** sp)
+                                                           const AbstractMethod* referrer,
+                                                           Thread* self,
+                                                           AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   // Called when caller isn't guaranteed to have access to a type and the dex cache may be
   // unpopulated.
@@ -47,8 +48,8 @@
   return ResolveVerifyAndClinit(type_idx, referrer, self, false, true);
 }
 
-extern "C" String* artResolveStringFromCode(Method* referrer, int32_t string_idx,
-                                            Thread* self, Method** sp)
+extern "C" String* artResolveStringFromCode(AbstractMethod* referrer, int32_t string_idx,
+                                            Thread* self, AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
   return ResolveStringFromCode(referrer, string_idx);
diff --git a/src/oat/runtime/support_field.cc b/src/oat/runtime/support_field.cc
index 90a99da..53b53b2 100644
--- a/src/oat/runtime/support_field.cc
+++ b/src/oat/runtime/support_field.cc
@@ -21,8 +21,8 @@
 
 namespace art {
 
-extern "C" uint32_t artGet32StaticFromCode(uint32_t field_idx, const Method* referrer,
-                                           Thread* self, Method** sp)
+extern "C" uint32_t artGet32StaticFromCode(uint32_t field_idx, const AbstractMethod* referrer,
+                                           Thread* self, AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int32_t));
   if (LIKELY(field != NULL)) {
@@ -36,8 +36,8 @@
   return 0;  // Will throw exception by checking with Thread::Current
 }
 
-extern "C" uint64_t artGet64StaticFromCode(uint32_t field_idx, const Method* referrer,
-                                           Thread* self, Method** sp)
+extern "C" uint64_t artGet64StaticFromCode(uint32_t field_idx, const AbstractMethod* referrer,
+                                           Thread* self, AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int64_t));
   if (LIKELY(field != NULL)) {
@@ -51,8 +51,8 @@
   return 0;  // Will throw exception by checking with Thread::Current
 }
 
-extern "C" Object* artGetObjStaticFromCode(uint32_t field_idx, const Method* referrer,
-                                           Thread* self, Method** sp)
+extern "C" Object* artGetObjStaticFromCode(uint32_t field_idx, const AbstractMethod* referrer,
+                                           Thread* self, AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   Field* field = FindFieldFast(field_idx, referrer, StaticObjectRead, sizeof(Object*));
   if (LIKELY(field != NULL)) {
@@ -67,7 +67,8 @@
 }
 
 extern "C" uint32_t artGet32InstanceFromCode(uint32_t field_idx, Object* obj,
-                                             const Method* referrer, Thread* self, Method** sp)
+                                             const AbstractMethod* referrer, Thread* self,
+                                             AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int32_t));
   if (LIKELY(field != NULL && obj != NULL)) {
@@ -86,7 +87,8 @@
 }
 
 extern "C" uint64_t artGet64InstanceFromCode(uint32_t field_idx, Object* obj,
-                                             const Method* referrer, Thread* self, Method** sp)
+                                             const AbstractMethod* referrer, Thread* self,
+                                             AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int64_t));
   if (LIKELY(field != NULL && obj != NULL)) {
@@ -105,7 +107,8 @@
 }
 
 extern "C" Object* artGetObjInstanceFromCode(uint32_t field_idx, Object* obj,
-                                              const Method* referrer, Thread* self, Method** sp)
+                                              const AbstractMethod* referrer, Thread* self,
+                                              AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   Field* field = FindFieldFast(field_idx, referrer, InstanceObjectRead, sizeof(Object*));
   if (LIKELY(field != NULL && obj != NULL)) {
@@ -124,7 +127,8 @@
 }
 
 extern "C" int artSet32StaticFromCode(uint32_t field_idx, uint32_t new_value,
-                                      const Method* referrer, Thread* self, Method** sp)
+                                      const AbstractMethod* referrer, Thread* self,
+                                      AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int32_t));
   if (LIKELY(field != NULL)) {
@@ -140,8 +144,8 @@
   return -1;  // failure
 }
 
-extern "C" int artSet64StaticFromCode(uint32_t field_idx, const Method* referrer,
-                                      uint64_t new_value, Thread* self, Method** sp)
+extern "C" int artSet64StaticFromCode(uint32_t field_idx, const AbstractMethod* referrer,
+                                      uint64_t new_value, Thread* self, AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int64_t));
   if (LIKELY(field != NULL)) {
@@ -158,7 +162,8 @@
 }
 
 extern "C" int artSetObjStaticFromCode(uint32_t field_idx, Object* new_value,
-                                       const Method* referrer, Thread* self, Method** sp)
+                                       const AbstractMethod* referrer, Thread* self,
+                                       AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   Field* field = FindFieldFast(field_idx, referrer, StaticObjectWrite, sizeof(Object*));
   if (LIKELY(field != NULL)) {
@@ -177,7 +182,8 @@
 }
 
 extern "C" int artSet32InstanceFromCode(uint32_t field_idx, Object* obj, uint32_t new_value,
-                                        const Method* referrer, Thread* self, Method** sp)
+                                        const AbstractMethod* referrer, Thread* self,
+                                        AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int32_t));
   if (LIKELY(field != NULL && obj != NULL)) {
@@ -198,10 +204,10 @@
 }
 
 extern "C" int artSet64InstanceFromCode(uint32_t field_idx, Object* obj, uint64_t new_value,
-                                        Thread* self, Method** sp)
+                                        Thread* self, AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  Method* callee_save = Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsOnly);
-  Method* referrer = sp[callee_save->GetFrameSizeInBytes() / sizeof(Method*)];
+  AbstractMethod* callee_save = Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsOnly);
+  AbstractMethod* referrer = sp[callee_save->GetFrameSizeInBytes() / sizeof(AbstractMethod*)];
   Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int64_t));
   if (LIKELY(field != NULL  && obj != NULL)) {
     field->Set64(obj, new_value);
@@ -222,7 +228,8 @@
 }
 
 extern "C" int artSetObjInstanceFromCode(uint32_t field_idx, Object* obj, Object* new_value,
-                                         const Method* referrer, Thread* self, Method** sp)
+                                         const AbstractMethod* referrer, Thread* self,
+                                         AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   Field* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite, sizeof(Object*));
   if (LIKELY(field != NULL && obj != NULL)) {
diff --git a/src/oat/runtime/support_fillarray.cc b/src/oat/runtime/support_fillarray.cc
index 62b9cf9..9c6231f 100644
--- a/src/oat/runtime/support_fillarray.cc
+++ b/src/oat/runtime/support_fillarray.cc
@@ -37,7 +37,7 @@
  */
 extern "C" int artHandleFillArrayDataFromCode(Array* array,
                                               const Instruction::ArrayDataPayload* payload,
-                                              Thread* self, Method** sp)
+                                              Thread* self, AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
   DCHECK_EQ(payload->ident, static_cast<uint16_t>(Instruction::kArrayDataSignature));
diff --git a/src/oat/runtime/support_invoke.cc b/src/oat/runtime/support_invoke.cc
index 540e46b..87497cc 100644
--- a/src/oat/runtime/support_invoke.cc
+++ b/src/oat/runtime/support_invoke.cc
@@ -19,10 +19,10 @@
 
 namespace art {
 
-static uint64_t artInvokeCommon(uint32_t method_idx, Object* this_object, Method* caller_method,
-                                Thread* self, Method** sp, bool access_check, InvokeType type)
+static uint64_t artInvokeCommon(uint32_t method_idx, Object* this_object, AbstractMethod* caller_method,
+                                Thread* self, AbstractMethod** sp, bool access_check, InvokeType type)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  Method* method = FindMethodFast(method_idx, this_object, caller_method, access_check, type);
+  AbstractMethod* method = FindMethodFast(method_idx, this_object, caller_method, access_check, type);
   if (UNLIKELY(method == NULL)) {
     FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsAndArgs);
     if (UNLIKELY(this_object == NULL && type != kDirect && type != kStatic)) {
@@ -54,16 +54,17 @@
 
 // See comments in runtime_support_asm.S
 extern "C" uint64_t artInvokeInterfaceTrampoline(uint32_t method_idx, Object* this_object,
-                                                 Method* caller_method, Thread* self,
-                                                 Method** sp)
+                                                 AbstractMethod* caller_method, Thread* self,
+                                                 AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   return artInvokeCommon(method_idx, this_object, caller_method, self, sp, false, kInterface);
 }
 
 extern "C" uint64_t artInvokeInterfaceTrampolineWithAccessCheck(uint32_t method_idx,
                                                                 Object* this_object,
-                                                                Method* caller_method, Thread* self,
-                                                                Method** sp)
+                                                                AbstractMethod* caller_method,
+                                                                Thread* self,
+                                                                AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   return artInvokeCommon(method_idx, this_object, caller_method, self, sp, true, kInterface);
 }
@@ -71,32 +72,36 @@
 
 extern "C" uint64_t artInvokeDirectTrampolineWithAccessCheck(uint32_t method_idx,
                                                              Object* this_object,
-                                                             Method* caller_method, Thread* self,
-                                                             Method** sp)
+                                                             AbstractMethod* caller_method,
+                                                             Thread* self,
+                                                             AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   return artInvokeCommon(method_idx, this_object, caller_method, self, sp, true, kDirect);
 }
 
 extern "C" uint64_t artInvokeStaticTrampolineWithAccessCheck(uint32_t method_idx,
                                                             Object* this_object,
-                                                            Method* caller_method, Thread* self,
-                                                            Method** sp)
+                                                            AbstractMethod* caller_method,
+                                                            Thread* self,
+                                                            AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   return artInvokeCommon(method_idx, this_object, caller_method, self, sp, true, kStatic);
 }
 
 extern "C" uint64_t artInvokeSuperTrampolineWithAccessCheck(uint32_t method_idx,
                                                             Object* this_object,
-                                                            Method* caller_method, Thread* self,
-                                                            Method** sp)
+                                                            AbstractMethod* caller_method,
+                                                            Thread* self,
+                                                            AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   return artInvokeCommon(method_idx, this_object, caller_method, self, sp, true, kSuper);
 }
 
 extern "C" uint64_t artInvokeVirtualTrampolineWithAccessCheck(uint32_t method_idx,
                                                               Object* this_object,
-                                                              Method* caller_method, Thread* self,
-                                                              Method** sp)
+                                                              AbstractMethod* caller_method,
+                                                              Thread* self,
+                                                              AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   return artInvokeCommon(method_idx, this_object, caller_method, self, sp, true, kVirtual);
 }
diff --git a/src/oat/runtime/support_jni.cc b/src/oat/runtime/support_jni.cc
index 2c6f766..6116d56 100644
--- a/src/oat/runtime/support_jni.cc
+++ b/src/oat/runtime/support_jni.cc
@@ -28,7 +28,7 @@
   DCHECK(Thread::Current() == self);
   ScopedObjectAccess soa(self);
 
-  Method* method = self->GetCurrentMethod();
+  AbstractMethod* method = self->GetCurrentMethod();
   DCHECK(method != NULL);
 
   // Lookup symbol address for method, on failure we'll return NULL with an
@@ -136,7 +136,7 @@
   // | unused |
   // | unused |
   // | unused | <- sp
-  Method* jni_method = self->GetCurrentMethod();
+  AbstractMethod* jni_method = self->GetCurrentMethod();
   DCHECK(jni_method->IsNative()) << PrettyMethod(jni_method);
   intptr_t* arg_ptr = sp + 4;  // pointer to r1 on stack
   // Fix up this/jclass argument
diff --git a/src/oat/runtime/support_locks.cc b/src/oat/runtime/support_locks.cc
index 9d44e55..f3a3106 100644
--- a/src/oat/runtime/support_locks.cc
+++ b/src/oat/runtime/support_locks.cc
@@ -19,7 +19,7 @@
 
 namespace art {
 
-extern "C" int artUnlockObjectFromCode(Object* obj, Thread* self, Method** sp)
+extern "C" int artUnlockObjectFromCode(Object* obj, Thread* self, AbstractMethod** sp)
     UNLOCK_FUNCTION(monitor_lock_) {
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
   DCHECK(obj != NULL);  // Assumed to have been checked before entry
@@ -27,7 +27,7 @@
   return obj->MonitorExit(self) ? 0 /* Success */ : -1 /* Failure */;
 }
 
-extern "C" void artLockObjectFromCode(Object* obj, Thread* thread, Method** sp)
+extern "C" void artLockObjectFromCode(Object* obj, Thread* thread, AbstractMethod** sp)
     EXCLUSIVE_LOCK_FUNCTION(monitor_lock_) {
   FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsOnly);
   DCHECK(obj != NULL);        // Assumed to have been checked before entry
diff --git a/src/oat/runtime/support_proxy.cc b/src/oat/runtime/support_proxy.cc
index 8c40aba..4ff2e5f 100644
--- a/src/oat/runtime/support_proxy.cc
+++ b/src/oat/runtime/support_proxy.cc
@@ -46,11 +46,11 @@
 // which is responsible for recording callee save registers. We explicitly handlerize incoming
 // reference arguments (so they survive GC) and create a boxed argument array. Finally we invoke
 // the invocation handler which is a field within the proxy object receiver.
-extern "C" void artProxyInvokeHandler(Method* proxy_method, Object* receiver,
+extern "C" void artProxyInvokeHandler(AbstractMethod* proxy_method, Object* receiver,
                                       Thread* self, byte* stack_args)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   // Register the top of the managed stack
-  Method** proxy_sp = reinterpret_cast<Method**>(stack_args - SP_OFFSET_IN_BYTES);
+  AbstractMethod** proxy_sp = reinterpret_cast<AbstractMethod**>(stack_args - SP_OFFSET_IN_BYTES);
   DCHECK_EQ(*proxy_sp, proxy_method);
   self->SetTopOfStack(proxy_sp, 0);
   DCHECK_EQ(proxy_method->GetFrameSizeInBytes(), FRAME_SIZE_IN_BYTES);
@@ -112,7 +112,7 @@
     args_jobj[2].l = soa.AddLocalReference<jobjectArray>(args);
   }
   // Convert proxy method into expected interface method
-  Method* interface_method = proxy_method->FindOverriddenMethod();
+  AbstractMethod* interface_method = proxy_method->FindOverriddenMethod();
   DCHECK(interface_method != NULL);
   DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method);
   args_jobj[1].l = soa.AddLocalReference<jobject>(interface_method);
diff --git a/src/oat/runtime/support_stubs.cc b/src/oat/runtime/support_stubs.cc
index 5df7da3..fa8356e 100644
--- a/src/oat/runtime/support_stubs.cc
+++ b/src/oat/runtime/support_stubs.cc
@@ -32,7 +32,7 @@
 
 #if !defined(ART_USE_LLVM_COMPILER)
 // Lazily resolve a method. Called by stub code.
-const void* UnresolvedDirectMethodTrampolineFromCode(Method* called, Method** sp, Thread* thread,
+const void* UnresolvedDirectMethodTrampolineFromCode(AbstractMethod* called, AbstractMethod** sp, Thread* thread,
                                                      Runtime::TrampolineType type)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if defined(__arm__)
@@ -52,7 +52,7 @@
   // | R0         |
   // | Method*    |  <- sp
   DCHECK_EQ(48U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
-  Method** caller_sp = reinterpret_cast<Method**>(reinterpret_cast<byte*>(sp) + 48);
+  AbstractMethod** caller_sp = reinterpret_cast<AbstractMethod**>(reinterpret_cast<byte*>(sp) + 48);
   uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp) + kPointerSize);
   uintptr_t caller_pc = regs[10];
 #elif defined(__i386__)
@@ -71,12 +71,12 @@
   // | ECX         |    arg1
   // | EAX/Method* |  <- sp
   DCHECK_EQ(32U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
-  Method** caller_sp = reinterpret_cast<Method**>(reinterpret_cast<byte*>(sp) + 32);
+  AbstractMethod** caller_sp = reinterpret_cast<AbstractMethod**>(reinterpret_cast<byte*>(sp) + 32);
   uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp));
   uintptr_t caller_pc = regs[7];
 #else
   UNIMPLEMENTED(FATAL);
-  Method** caller_sp = NULL;
+  AbstractMethod** caller_sp = NULL;
   uintptr_t* regs = NULL;
   uintptr_t caller_pc = 0;
 #endif
@@ -88,7 +88,7 @@
 
   // Compute details about the called method (avoid GCs)
   ClassLinker* linker = Runtime::Current()->GetClassLinker();
-  Method* caller = *caller_sp;
+  AbstractMethod* caller = *caller_sp;
   InvokeType invoke_type;
   uint32_t dex_method_idx;
 #if !defined(__i386__)
@@ -227,11 +227,11 @@
   return code;
 }
 #else // ART_USE_LLVM_COMPILER
-const void* UnresolvedDirectMethodTrampolineFromCode(Method* called, Method** called_addr,
+const void* UnresolvedDirectMethodTrampolineFromCode(AbstractMethod* called, AbstractMethod** called_addr,
                                                      Thread* thread, Runtime::TrampolineType type)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   uint32_t dex_pc;
-  Method* caller = thread->GetCurrentMethod(&dex_pc);
+  AbstractMethod* caller = thread->GetCurrentMethod(&dex_pc);
 
   ClassLinker* linker = Runtime::Current()->GetClassLinker();
   InvokeType invoke_type;
@@ -321,7 +321,7 @@
 
 #if !defined(ART_USE_LLVM_COMPILER)
 // Called by the AbstractMethodError. Called by stub code.
-extern void ThrowAbstractMethodErrorFromCode(Method* method, Thread* thread, Method** sp)
+extern void ThrowAbstractMethodErrorFromCode(AbstractMethod* method, Thread* thread, AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
   thread->ThrowNewExceptionF("Ljava/lang/AbstractMethodError;",
@@ -329,7 +329,7 @@
   thread->DeliverException();
 }
 #else // ART_USE_LLVM_COMPILER
-extern void ThrowAbstractMethodErrorFromCode(Method* method, Thread* thread, Method**)
+extern void ThrowAbstractMethodErrorFromCode(AbstractMethod* method, Thread* thread, AbstractMethod**)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   thread->ThrowNewExceptionF("Ljava/lang/AbstractMethodError;",
                              "abstract method \"%s\"", PrettyMethod(method).c_str());
diff --git a/src/oat/runtime/support_thread.cc b/src/oat/runtime/support_thread.cc
index 20fe3e5..2eef424 100644
--- a/src/oat/runtime/support_thread.cc
+++ b/src/oat/runtime/support_thread.cc
@@ -27,7 +27,7 @@
   thread->FullSuspendCheck();
 }
 
-extern "C" void artTestSuspendFromCode(Thread* thread, Method** sp)
+extern "C" void artTestSuspendFromCode(Thread* thread, AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   // Called when suspend count check value is 0 and thread->suspend_count_ != 0
   FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsOnly);
diff --git a/src/oat/runtime/support_throw.cc b/src/oat/runtime/support_throw.cc
index 6e1e101..12295b1 100644
--- a/src/oat/runtime/support_throw.cc
+++ b/src/oat/runtime/support_throw.cc
@@ -23,14 +23,15 @@
 namespace art {
 
 // Deliver an exception that's pending on thread helping set up a callee save frame on the way.
-extern "C" void artDeliverPendingExceptionFromCode(Thread* thread, Method** sp)
+extern "C" void artDeliverPendingExceptionFromCode(Thread* thread, AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
   thread->DeliverException();
 }
 
 // Called by generated call to throw an exception.
-extern "C" void artDeliverExceptionFromCode(Throwable* exception, Thread* thread, Method** sp)
+extern "C" void artDeliverExceptionFromCode(Throwable* exception, Thread* thread,
+                                            AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   /*
    * exception may be NULL, in which case this routine should
@@ -49,17 +50,19 @@
 }
 
 // Called by generated call to throw a NPE exception.
-extern "C" void artThrowNullPointerExceptionFromCode(Thread* self, Method** sp)
+extern "C" void artThrowNullPointerExceptionFromCode(Thread* self,
+                                                     AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll);
   uint32_t dex_pc;
-  Method* throw_method = self->GetCurrentMethod(&dex_pc);
+  AbstractMethod* throw_method = self->GetCurrentMethod(&dex_pc);
   ThrowNullPointerExceptionFromDexPC(throw_method, dex_pc);
   self->DeliverException();
 }
 
 // Called by generated call to throw an arithmetic divide by zero exception.
-extern "C" void artThrowDivZeroFromCode(Thread* thread, Method** sp)
+extern "C" void artThrowDivZeroFromCode(Thread* thread,
+                                        AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
   thread->ThrowNewException("Ljava/lang/ArithmeticException;", "divide by zero");
@@ -67,7 +70,8 @@
 }
 
 // Called by generated call to throw an array index out of bounds exception.
-extern "C" void artThrowArrayBoundsFromCode(int index, int limit, Thread* thread, Method** sp)
+extern "C" void artThrowArrayBoundsFromCode(int index, int limit, Thread* thread,
+                                            AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
   thread->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
@@ -75,7 +79,7 @@
   thread->DeliverException();
 }
 
-extern "C" void artThrowStackOverflowFromCode(Thread* thread, Method** sp)
+extern "C" void artThrowStackOverflowFromCode(Thread* thread, AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
   // Remove extra entry pushed onto second stack during method tracing.
@@ -89,10 +93,11 @@
   thread->DeliverException();
 }
 
-extern "C" void artThrowNoSuchMethodFromCode(int32_t method_idx, Thread* self, Method** sp)
+extern "C" void artThrowNoSuchMethodFromCode(int32_t method_idx, Thread* self,
+                                             AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll);
-  Method* method = self->GetCurrentMethod();
+  AbstractMethod* method = self->GetCurrentMethod();
   ThrowNoSuchMethodError(method_idx, method);
   self->DeliverException();
 }
diff --git a/src/oat/runtime/support_trace.cc b/src/oat/runtime/support_trace.cc
index c6fbfef..67317a9 100644
--- a/src/oat/runtime/support_trace.cc
+++ b/src/oat/runtime/support_trace.cc
@@ -20,7 +20,7 @@
 
 namespace art {
 
-extern "C" const void* artTraceMethodEntryFromCode(Method* method, Thread* self, uintptr_t lr) {
+extern "C" const void* artTraceMethodEntryFromCode(AbstractMethod* method, Thread* self, uintptr_t lr) {
   Trace* tracer = Runtime::Current()->GetTracer();
   TraceStackFrame trace_frame = TraceStackFrame(method, lr);
   self->PushTraceStackFrame(trace_frame);
@@ -33,7 +33,7 @@
 extern "C" uintptr_t artTraceMethodExitFromCode() {
   Trace* tracer = Runtime::Current()->GetTracer();
   TraceStackFrame trace_frame = Thread::Current()->PopTraceStackFrame();
-  Method* method = trace_frame.method_;
+  AbstractMethod* method = trace_frame.method_;
   uintptr_t lr = trace_frame.return_pc_;
 
   tracer->LogMethodTraceEvent(Thread::Current(), method, Trace::kMethodTraceExit);
diff --git a/src/oat/runtime/x86/context_x86.cc b/src/oat/runtime/x86/context_x86.cc
index 4d84f2b..4ff2283 100644
--- a/src/oat/runtime/x86/context_x86.cc
+++ b/src/oat/runtime/x86/context_x86.cc
@@ -32,7 +32,7 @@
 }
 
 void X86Context::FillCalleeSaves(const StackVisitor& fr) {
-  Method* method = fr.GetMethod();
+  AbstractMethod* method = fr.GetMethod();
   uint32_t core_spills = method->GetCoreSpillMask();
   size_t spill_count = __builtin_popcount(core_spills);
   DCHECK_EQ(method->GetFpSpillMask(), 0u);
diff --git a/src/oat/runtime/x86/oat_support_entrypoints_x86.cc b/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
index 9ff4a07..b4eaf60 100644
--- a/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
+++ b/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
@@ -33,7 +33,7 @@
 extern "C" void art_check_cast_from_code(void*, void*);
 
 // Debug entrypoints.
-extern void DebugMe(Method* method, uint32_t info);
+extern void DebugMe(AbstractMethod* method, uint32_t info);
 
 // DexCache entrypoints.
 extern "C" void* art_initialize_static_storage_from_code(uint32_t, void*);
@@ -97,7 +97,7 @@
 extern "C" void* art_memcpy(void*, const void*, size_t);
 
 // Invoke entrypoints.
-const void* UnresolvedDirectMethodTrampolineFromCode(Method*, Method**, Thread*,
+const void* UnresolvedDirectMethodTrampolineFromCode(AbstractMethod*, AbstractMethod**, Thread*,
                                                      Runtime::TrampolineType);
 extern "C" void art_invoke_direct_trampoline_with_access_check(uint32_t, void*);
 extern "C" void art_invoke_interface_trampoline(uint32_t, void*);
@@ -111,7 +111,7 @@
 extern "C" void art_test_suspend();
 
 // Throw entrypoints.
-extern void ThrowAbstractMethodErrorFromCode(Method* method, Thread* thread, Method** sp);
+extern void ThrowAbstractMethodErrorFromCode(AbstractMethod* method, Thread* thread, AbstractMethod** sp);
 extern "C" void art_deliver_exception_from_code(void*);
 extern "C" void art_throw_array_bounds_from_code(int32_t index, int32_t limit);
 extern "C" void art_throw_div_zero_from_code();
diff --git a/src/oat/runtime/x86/stub_x86.cc b/src/oat/runtime/x86/stub_x86.cc
index 74e0f39..97b686f 100644
--- a/src/oat/runtime/x86/stub_x86.cc
+++ b/src/oat/runtime/x86/stub_x86.cc
@@ -99,7 +99,7 @@
   return resolution_trampoline.get();
 }
 
-typedef void (*ThrowAme)(Method*, Thread*);
+typedef void (*ThrowAme)(AbstractMethod*, Thread*);
 
 ByteArray* CreateAbstractMethodErrorStub() {
   UniquePtr<X86Assembler> assembler(static_cast<X86Assembler*>(Assembler::Create(kX86)));
diff --git a/src/oat_file.cc b/src/oat_file.cc
index 2a21baa..93ff7a6 100644
--- a/src/oat_file.cc
+++ b/src/oat_file.cc
@@ -334,9 +334,9 @@
   return reinterpret_cast<uint32_t*>(code)[-1];
 }
 
-Method::InvokeStub* OatFile::OatMethod::GetInvokeStub() const {
+AbstractMethod::InvokeStub* OatFile::OatMethod::GetInvokeStub() const {
   const byte* stub = GetOatPointer<const byte*>(invoke_stub_offset_);
-  return reinterpret_cast<Method::InvokeStub*>(const_cast<byte*>(stub));
+  return reinterpret_cast<AbstractMethod::InvokeStub*>(const_cast<byte*>(stub));
 }
 
 uint32_t OatFile::OatMethod::GetInvokeStubSize() const {
@@ -355,7 +355,7 @@
 }
 #endif
 
-void OatFile::OatMethod::LinkMethodPointers(Method* method) const {
+void OatFile::OatMethod::LinkMethodPointers(AbstractMethod* method) const {
   CHECK(method != NULL);
   method->SetCode(GetCode());
   method->SetFrameSizeInBytes(frame_size_in_bytes_);
@@ -367,7 +367,7 @@
   method->SetInvokeStub(GetInvokeStub());
 }
 
-void OatFile::OatMethod::LinkMethodOffsets(Method* method) const {
+void OatFile::OatMethod::LinkMethodOffsets(AbstractMethod* method) const {
   CHECK(method != NULL);
   method->SetOatCodeOffset(GetCodeOffset());
   method->SetFrameSizeInBytes(GetFrameSizeInBytes());
diff --git a/src/oat_file.h b/src/oat_file.h
index 91df927..de7cf14 100644
--- a/src/oat_file.h
+++ b/src/oat_file.h
@@ -65,10 +65,10 @@
   class OatMethod {
    public:
     // Link Method for execution using the contents of this OatMethod
-    void LinkMethodPointers(Method* method) const;
+    void LinkMethodPointers(AbstractMethod* method) const;
 
     // Link Method for image writing using the contents of this OatMethod
-    void LinkMethodOffsets(Method* method) const;
+    void LinkMethodOffsets(AbstractMethod* method) const;
 
     uint32_t GetCodeOffset() const {
       return code_offset_;
@@ -108,7 +108,7 @@
       return GetOatPointer<const uint8_t*>(native_gc_map_offset_);
     }
 
-    Method::InvokeStub* GetInvokeStub() const;
+    AbstractMethod::InvokeStub* GetInvokeStub() const;
     uint32_t GetInvokeStubSize() const;
 
 #if defined(ART_USE_LLVM_COMPILER)
diff --git a/src/oat_test.cc b/src/oat_test.cc
index 0886864..ae4aae2 100644
--- a/src/oat_test.cc
+++ b/src/oat_test.cc
@@ -23,7 +23,7 @@
 
 class OatTest : public CommonTest {
  protected:
-  void CheckMethod(Method* method,
+  void CheckMethod(AbstractMethod* method,
                    const OatFile::OatMethod& oat_method,
                    const DexFile* dex_file)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
diff --git a/src/oat_writer.cc b/src/oat_writer.cc
index 2eb80ec..2969c21 100644
--- a/src/oat_writer.cc
+++ b/src/oat_writer.cc
@@ -397,7 +397,7 @@
     DexCache* dex_cache = linker->FindDexCache(*dex_file);
     // Unchecked as we hold mutator_lock_ on entry.
     ScopedObjectAccessUnchecked soa(Thread::Current());
-    Method* method = linker->ResolveMethod(*dex_file, method_idx, dex_cache,
+    AbstractMethod* method = linker->ResolveMethod(*dex_file, method_idx, dex_cache,
                                            soa.Decode<ClassLoader*>(class_loader_), NULL, type);
     CHECK(method != NULL);
     method->SetFrameSizeInBytes(frame_size_in_bytes);
diff --git a/src/oatdump.cc b/src/oatdump.cc
index d3bebfd..88d6976 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -156,7 +156,7 @@
     return oat_file_.GetOatHeader().GetInstructionSet();
   }
 
-  const void* GetOatCode(Method* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  const void* GetOatCode(AbstractMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     MethodHelper mh(m);
     for (size_t i = 0; i < oat_dex_files_.size(); i++) {
       const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i];
@@ -611,7 +611,7 @@
       Field* field = value->AsField();
       StringAppendF(&summary, "%p   Field: %s\n", field, PrettyField(field).c_str());
     } else if (value->IsMethod()) {
-      Method* method = value->AsMethod();
+      AbstractMethod* method = value->AsMethod();
       StringAppendF(&summary, "%p   Method: %s\n", method, PrettyMethod(method).c_str());
     } else {
       StringAppendF(&summary, "%p   %s\n", value, PrettyDescriptor(type).c_str());
@@ -666,7 +666,7 @@
     return image_space_.Contains(object);
   }
 
-  const void* GetOatCodeBegin(Method* m)
+  const void* GetOatCodeBegin(AbstractMethod* m)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     Runtime* runtime = Runtime::Current();
     const void* code = m->GetCode();
@@ -679,7 +679,7 @@
     return code;
   }
 
-  uint32_t GetOatCodeSize(Method* m)
+  uint32_t GetOatCodeSize(AbstractMethod* m)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     const uint32_t* oat_code_begin = reinterpret_cast<const uint32_t*>(GetOatCodeBegin(m));
     if (oat_code_begin == NULL) {
@@ -688,7 +688,7 @@
     return oat_code_begin[-1];
   }
 
-  const void* GetOatCodeEnd(Method* m)
+  const void* GetOatCodeEnd(AbstractMethod* m)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     const uint8_t* oat_code_begin = reinterpret_cast<const uint8_t*>(GetOatCodeBegin(m));
     if (oat_code_begin == NULL) {
@@ -768,7 +768,7 @@
         }
       }
     } else if (obj->IsMethod()) {
-      Method* method = obj->AsMethod();
+      AbstractMethod* method = obj->AsMethod();
       if (method->IsNative()) {
         DCHECK(method->GetNativeGcMap() == NULL) << PrettyMethod(method);
         DCHECK(method->GetMappingTable() == NULL) << PrettyMethod(method);
@@ -895,7 +895,7 @@
 
     size_t dex_instruction_bytes;
 
-    std::vector<Method*> method_outlier;
+    std::vector<AbstractMethod*> method_outlier;
     std::vector<size_t> method_outlier_size;
     std::vector<double> method_outlier_expansion;
 
@@ -947,7 +947,7 @@
       return (static_cast<double>(size) / static_cast<double>(object_bytes)) * 100;
     }
 
-    void ComputeOutliers(size_t total_size, double expansion, Method* method) {
+    void ComputeOutliers(size_t total_size, double expansion, AbstractMethod* method) {
       method_outlier_size.push_back(total_size);
       method_outlier_expansion.push_back(expansion);
       method_outlier.push_back(method);
diff --git a/src/oatexec.cc b/src/oatexec.cc
index 49c0706..8908abb 100644
--- a/src/oatexec.cc
+++ b/src/oatexec.cc
@@ -40,7 +40,8 @@
   }
   // We now have a Method instance.  We need to call its
   // getModifiers() method.
-  jmethodID mid = env->GetMethodID(WellKnownClasses::java_lang_reflect_Method, "getModifiers", "()I");
+  jmethodID mid = env->GetMethodID(WellKnownClasses::java_lang_reflect_AbstractMethod,
+                                   "getModifiers", "()I");
   if (mid == NULL) {
     fprintf(stderr, "Failed to find java.lang.reflect.Method.getModifiers\n");
     return false;
diff --git a/src/object.cc b/src/object.cc
index f2043b1..e4b5f98 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -313,10 +313,10 @@
 }
 
 // TODO: get global references for these
-Class* Method::java_lang_reflect_Constructor_ = NULL;
-Class* Method::java_lang_reflect_Method_ = NULL;
+Class* AbstractMethod::java_lang_reflect_Constructor_ = NULL;
+Class* AbstractMethod::java_lang_reflect_Method_ = NULL;
 
-InvokeType Method::GetInvokeType() const {
+InvokeType AbstractMethod::GetInvokeType() const {
   // TODO: kSuper?
   if (GetDeclaringClass()->IsInterface()) {
     return kInterface;
@@ -329,7 +329,7 @@
   }
 }
 
-void Method::SetClasses(Class* java_lang_reflect_Constructor, Class* java_lang_reflect_Method) {
+void AbstractMethod::SetClasses(Class* java_lang_reflect_Constructor, Class* java_lang_reflect_Method) {
   CHECK(java_lang_reflect_Constructor_ == NULL);
   CHECK(java_lang_reflect_Constructor != NULL);
   java_lang_reflect_Constructor_ = java_lang_reflect_Constructor;
@@ -339,7 +339,7 @@
   java_lang_reflect_Method_ = java_lang_reflect_Method;
 }
 
-void Method::ResetClasses() {
+void AbstractMethod::ResetClasses() {
   CHECK(java_lang_reflect_Constructor_ != NULL);
   java_lang_reflect_Constructor_ = NULL;
 
@@ -347,48 +347,48 @@
   java_lang_reflect_Method_ = NULL;
 }
 
-ObjectArray<String>* Method::GetDexCacheStrings() const {
+ObjectArray<String>* AbstractMethod::GetDexCacheStrings() const {
   return GetFieldObject<ObjectArray<String>*>(
-      OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_strings_), false);
+      OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_strings_), false);
 }
 
-void Method::SetDexCacheStrings(ObjectArray<String>* new_dex_cache_strings) {
-  SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_strings_),
+void AbstractMethod::SetDexCacheStrings(ObjectArray<String>* new_dex_cache_strings) {
+  SetFieldObject(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_strings_),
                  new_dex_cache_strings, false);
 }
 
-ObjectArray<Method>* Method::GetDexCacheResolvedMethods() const {
-  return GetFieldObject<ObjectArray<Method>*>(
-      OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_methods_), false);
+ObjectArray<AbstractMethod>* AbstractMethod::GetDexCacheResolvedMethods() const {
+  return GetFieldObject<ObjectArray<AbstractMethod>*>(
+      OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_resolved_methods_), false);
 }
 
-void Method::SetDexCacheResolvedMethods(ObjectArray<Method>* new_dex_cache_methods) {
-  SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_methods_),
+void AbstractMethod::SetDexCacheResolvedMethods(ObjectArray<AbstractMethod>* new_dex_cache_methods) {
+  SetFieldObject(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_resolved_methods_),
                  new_dex_cache_methods, false);
 }
 
-ObjectArray<Class>* Method::GetDexCacheResolvedTypes() const {
+ObjectArray<Class>* AbstractMethod::GetDexCacheResolvedTypes() const {
   return GetFieldObject<ObjectArray<Class>*>(
-      OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_types_), false);
+      OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_resolved_types_), false);
 }
 
-void Method::SetDexCacheResolvedTypes(ObjectArray<Class>* new_dex_cache_classes) {
-  SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_types_),
+void AbstractMethod::SetDexCacheResolvedTypes(ObjectArray<Class>* new_dex_cache_classes) {
+  SetFieldObject(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_resolved_types_),
                  new_dex_cache_classes, false);
 }
 
-ObjectArray<StaticStorageBase>* Method::GetDexCacheInitializedStaticStorage() const {
+ObjectArray<StaticStorageBase>* AbstractMethod::GetDexCacheInitializedStaticStorage() const {
   return GetFieldObject<ObjectArray<StaticStorageBase>*>(
-      OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_initialized_static_storage_),
+      OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_initialized_static_storage_),
       false);
 }
 
-void Method::SetDexCacheInitializedStaticStorage(ObjectArray<StaticStorageBase>* new_value) {
-  SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_initialized_static_storage_),
+void AbstractMethod::SetDexCacheInitializedStaticStorage(ObjectArray<StaticStorageBase>* new_value) {
+  SetFieldObject(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_initialized_static_storage_),
       new_value, false);
 }
 
-size_t Method::NumArgRegisters(const StringPiece& shorty) {
+size_t AbstractMethod::NumArgRegisters(const StringPiece& shorty) {
   CHECK_LE(1, shorty.length());
   uint32_t num_registers = 0;
   for (int i = 1; i < shorty.length(); ++i) {
@@ -402,19 +402,19 @@
   return num_registers;
 }
 
-bool Method::IsProxyMethod() const {
+bool AbstractMethod::IsProxyMethod() const {
   return GetDeclaringClass()->IsProxyClass();
 }
 
-Method* Method::FindOverriddenMethod() const {
+AbstractMethod* AbstractMethod::FindOverriddenMethod() const {
   if (IsStatic()) {
     return NULL;
   }
   Class* declaring_class = GetDeclaringClass();
   Class* super_class = declaring_class->GetSuperClass();
   uint16_t method_index = GetMethodIndex();
-  ObjectArray<Method>* super_class_vtable = super_class->GetVTable();
-  Method* result = NULL;
+  ObjectArray<AbstractMethod>* super_class_vtable = super_class->GetVTable();
+  AbstractMethod* result = NULL;
   // Did this method override a super class method? If so load the result from the super class'
   // vtable
   if (super_class_vtable != NULL && method_index < super_class_vtable->GetLength()) {
@@ -433,7 +433,7 @@
         InterfaceEntry* entry = iftable->Get(i);
         Class* interface = entry->GetInterface();
         for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
-          Method* interface_method = interface->GetVirtualMethod(j);
+          AbstractMethod* interface_method = interface->GetVirtualMethod(j);
           interface_mh.ChangeMethod(interface_method);
           if (mh.HasSameNameAndSignature(&interface_mh)) {
             result = interface_method;
@@ -450,7 +450,8 @@
   return result;
 }
 
-static const void* GetOatCode(const Method* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+static const void* GetOatCode(const AbstractMethod* m)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   Runtime* runtime = Runtime::Current();
   const void* code = m->GetCode();
   // Peel off any method tracing trampoline.
@@ -464,11 +465,11 @@
   return code;
 }
 
-uintptr_t Method::NativePcOffset(const uintptr_t pc) const {
+uintptr_t AbstractMethod::NativePcOffset(const uintptr_t pc) const {
   return pc - reinterpret_cast<uintptr_t>(GetOatCode(this));
 }
 
-uint32_t Method::ToDexPc(const uintptr_t pc) const {
+uint32_t AbstractMethod::ToDexPc(const uintptr_t pc) const {
 #if !defined(ART_USE_LLVM_COMPILER)
   const uint32_t* mapping_table = GetMappingTable();
   if (mapping_table == NULL) {
@@ -491,7 +492,7 @@
 #endif
 }
 
-uintptr_t Method::ToNativePc(const uint32_t dex_pc) const {
+uintptr_t AbstractMethod::ToNativePc(const uint32_t dex_pc) const {
   const uint32_t* mapping_table = GetMappingTable();
   if (mapping_table == NULL) {
     DCHECK_EQ(dex_pc, 0U);
@@ -509,7 +510,7 @@
   return 0;
 }
 
-uint32_t Method::FindCatchBlock(Class* exception_type, uint32_t dex_pc) const {
+uint32_t AbstractMethod::FindCatchBlock(Class* exception_type, uint32_t dex_pc) const {
   MethodHelper mh(this);
   const DexFile::CodeItem* code_item = mh.GetCodeItem();
   // Iterate over the catch handlers associated with dex_pc
@@ -533,7 +534,7 @@
   return DexFile::kDexNoIndex;
 }
 
-void Method::Invoke(Thread* self, Object* receiver, JValue* args, JValue* result) const {
+void AbstractMethod::Invoke(Thread* self, Object* receiver, JValue* args, JValue* result) const {
   if (kIsDebugBuild) {
     self->AssertThreadSuspensionIsAllowable();
     MutexLock mu(*Locks::thread_suspend_count_lock_);
@@ -546,7 +547,7 @@
 
   // Call the invoke stub associated with the method.
   // Pass everything as arguments.
-  Method::InvokeStub* stub = GetInvokeStub();
+  AbstractMethod::InvokeStub* stub = GetInvokeStub();
 
   bool have_executable_code = (GetCode() != NULL);
 
@@ -574,23 +575,23 @@
   self->PopManagedStackFragment(fragment);
 }
 
-bool Method::IsRegistered() const {
-  void* native_method = GetFieldPtr<void*>(OFFSET_OF_OBJECT_MEMBER(Method, native_method_), false);
+bool AbstractMethod::IsRegistered() const {
+  void* native_method = GetFieldPtr<void*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_method_), false);
   CHECK(native_method != NULL);
   void* jni_stub = Runtime::Current()->GetJniDlsymLookupStub()->GetData();
   return native_method != jni_stub;
 }
 
-void Method::RegisterNative(Thread* self, const void* native_method) {
+void AbstractMethod::RegisterNative(Thread* self, const void* native_method) {
   DCHECK(Thread::Current() == self);
   CHECK(IsNative()) << PrettyMethod(this);
   CHECK(native_method != NULL) << PrettyMethod(this);
 #if defined(ART_USE_LLVM_COMPILER)
-  SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(Method, native_method_),
+  SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_method_),
                            native_method, false);
 #else
   if (!self->GetJniEnv()->vm->work_around_app_jni_bugs) {
-    SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(Method, native_method_),
+    SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_method_),
                              native_method, false);
   } else {
     // We've been asked to associate this method with the given native method but are working
@@ -598,18 +599,18 @@
     // the native method to runtime support and store the target somewhere runtime support will
     // find it.
 #if defined(__arm__)
-    SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(Method, native_method_),
+    SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_method_),
         reinterpret_cast<const void*>(art_work_around_app_jni_bugs), false);
 #else
     UNIMPLEMENTED(FATAL);
 #endif
-    SetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(Method, native_gc_map_),
+    SetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_gc_map_),
         reinterpret_cast<const uint8_t*>(native_method), false);
   }
 #endif
 }
 
-void Method::UnregisterNative(Thread* self) {
+void AbstractMethod::UnregisterNative(Thread* self) {
   CHECK(IsNative()) << PrettyMethod(this);
   // restore stub to lookup native pointer via dlsym
   RegisterNative(self, Runtime::Current()->GetJniDlsymLookupStub()->GetData());
@@ -931,7 +932,7 @@
   SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_), new_class_loader, false);
 }
 
-Method* Class::FindVirtualMethodForInterface(Method* method) {
+AbstractMethod* Class::FindVirtualMethodForInterface(AbstractMethod* method) {
   Class* declaring_class = method->GetDeclaringClass();
   DCHECK(declaring_class != NULL) << PrettyClass(this);
   DCHECK(declaring_class->IsInterface()) << PrettyMethod(method);
@@ -947,9 +948,9 @@
   return NULL;
 }
 
-Method* Class::FindInterfaceMethod(const StringPiece& name,  const StringPiece& signature) const {
+AbstractMethod* Class::FindInterfaceMethod(const StringPiece& name,  const StringPiece& signature) const {
   // Check the current class before checking the interfaces.
-  Method* method = FindDeclaredVirtualMethod(name, signature);
+  AbstractMethod* method = FindDeclaredVirtualMethod(name, signature);
   if (method != NULL) {
     return method;
   }
@@ -965,9 +966,9 @@
   return NULL;
 }
 
-Method* Class::FindInterfaceMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const {
+AbstractMethod* Class::FindInterfaceMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const {
   // Check the current class before checking the interfaces.
-  Method* method = FindDeclaredVirtualMethod(dex_cache, dex_method_idx);
+  AbstractMethod* method = FindDeclaredVirtualMethod(dex_cache, dex_method_idx);
   if (method != NULL) {
     return method;
   }
@@ -984,10 +985,10 @@
 }
 
 
-Method* Class::FindDeclaredDirectMethod(const StringPiece& name, const StringPiece& signature) const {
+AbstractMethod* Class::FindDeclaredDirectMethod(const StringPiece& name, const StringPiece& signature) const {
   MethodHelper mh;
   for (size_t i = 0; i < NumDirectMethods(); ++i) {
-    Method* method = GetDirectMethod(i);
+    AbstractMethod* method = GetDirectMethod(i);
     mh.ChangeMethod(method);
     if (name == mh.GetName() && signature == mh.GetSignature()) {
       return method;
@@ -996,10 +997,10 @@
   return NULL;
 }
 
-Method* Class::FindDeclaredDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const {
+AbstractMethod* Class::FindDeclaredDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const {
   if (GetDexCache() == dex_cache) {
     for (size_t i = 0; i < NumDirectMethods(); ++i) {
-      Method* method = GetDirectMethod(i);
+      AbstractMethod* method = GetDirectMethod(i);
       if (method->GetDexMethodIndex() == dex_method_idx) {
         return method;
       }
@@ -1008,9 +1009,9 @@
   return NULL;
 }
 
-Method* Class::FindDirectMethod(const StringPiece& name, const StringPiece& signature) const {
+AbstractMethod* Class::FindDirectMethod(const StringPiece& name, const StringPiece& signature) const {
   for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
-    Method* method = klass->FindDeclaredDirectMethod(name, signature);
+    AbstractMethod* method = klass->FindDeclaredDirectMethod(name, signature);
     if (method != NULL) {
       return method;
     }
@@ -1018,9 +1019,9 @@
   return NULL;
 }
 
-Method* Class::FindDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const {
+AbstractMethod* Class::FindDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const {
   for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
-    Method* method = klass->FindDeclaredDirectMethod(dex_cache, dex_method_idx);
+    AbstractMethod* method = klass->FindDeclaredDirectMethod(dex_cache, dex_method_idx);
     if (method != NULL) {
       return method;
     }
@@ -1028,11 +1029,11 @@
   return NULL;
 }
 
-Method* Class::FindDeclaredVirtualMethod(const StringPiece& name,
+AbstractMethod* Class::FindDeclaredVirtualMethod(const StringPiece& name,
                                          const StringPiece& signature) const {
   MethodHelper mh;
   for (size_t i = 0; i < NumVirtualMethods(); ++i) {
-    Method* method = GetVirtualMethod(i);
+    AbstractMethod* method = GetVirtualMethod(i);
     mh.ChangeMethod(method);
     if (name == mh.GetName() && signature == mh.GetSignature()) {
       return method;
@@ -1041,10 +1042,10 @@
   return NULL;
 }
 
-Method* Class::FindDeclaredVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const {
+AbstractMethod* Class::FindDeclaredVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const {
   if (GetDexCache() == dex_cache) {
     for (size_t i = 0; i < NumVirtualMethods(); ++i) {
-      Method* method = GetVirtualMethod(i);
+      AbstractMethod* method = GetVirtualMethod(i);
       if (method->GetDexMethodIndex() == dex_method_idx) {
         return method;
       }
@@ -1053,9 +1054,9 @@
   return NULL;
 }
 
-Method* Class::FindVirtualMethod(const StringPiece& name, const StringPiece& signature) const {
+AbstractMethod* Class::FindVirtualMethod(const StringPiece& name, const StringPiece& signature) const {
   for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
-    Method* method = klass->FindDeclaredVirtualMethod(name, signature);
+    AbstractMethod* method = klass->FindDeclaredVirtualMethod(name, signature);
     if (method != NULL) {
       return method;
     }
@@ -1063,9 +1064,9 @@
   return NULL;
 }
 
-Method* Class::FindVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const {
+AbstractMethod* Class::FindVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const {
   for (const Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
-    Method* method = klass->FindDeclaredVirtualMethod(dex_cache, dex_method_idx);
+    AbstractMethod* method = klass->FindDeclaredVirtualMethod(dex_cache, dex_method_idx);
     if (method != NULL) {
       return method;
     }
@@ -1495,7 +1496,7 @@
     IntArray* pc_trace = down_cast<IntArray*>(method_trace->Get(depth));
     MethodHelper mh;
     for (int32_t i = 0; i < depth; ++i) {
-      Method* method = down_cast<Method*>(method_trace->Get(i));
+      AbstractMethod* method = down_cast<AbstractMethod*>(method_trace->Get(i));
       mh.ChangeMethod(method);
       uint32_t dex_pc = pc_trace->Get(i);
       int32_t line_number = mh.GetLineNumFromDexPC(dex_pc);
diff --git a/src/object.h b/src/object.h
index 5d19ffc..5a9a825 100644
--- a/src/object.h
+++ b/src/object.h
@@ -46,7 +46,8 @@
 class Field;
 class InterfaceEntry;
 class Monitor;
-class Method;
+class Member;
+class AbstractMethod;
 class Object;
 class StaticStorageBase;
 class String;
@@ -250,14 +251,14 @@
 
   bool IsMethod() const;
 
-  Method* AsMethod() {
+  AbstractMethod* AsMethod() {
     DCHECK(IsMethod());
-    return down_cast<Method*>(this);
+    return down_cast<AbstractMethod*>(this);
   }
 
-  const Method* AsMethod() const {
+  const AbstractMethod* AsMethod() const {
     DCHECK(IsMethod());
-    return down_cast<const Method*>(this);
+    return down_cast<const AbstractMethod*>(this);
   }
 
   bool IsField() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -506,10 +507,10 @@
 };
 
 // C++ mirror of java.lang.reflect.Method and java.lang.reflect.Constructor
-class MANAGED Method : public Object {
+class MANAGED AbstractMethod : public Object {
  public:
   // A function that invokes a method with an array of its arguments.
-  typedef void InvokeStub(const Method* method,
+  typedef void InvokeStub(const AbstractMethod* method,
                           Object* obj,
                           Thread* thread,
                           JValue* args,
@@ -520,13 +521,13 @@
   void SetDeclaringClass(Class *new_declaring_class);
 
   static MemberOffset DeclaringClassOffset() {
-    return MemberOffset(OFFSETOF_MEMBER(Method, declaring_class_));
+    return MemberOffset(OFFSETOF_MEMBER(AbstractMethod, declaring_class_));
   }
 
   uint32_t GetAccessFlags() const;
 
   void SetAccessFlags(uint32_t new_access_flags) {
-    SetField32(OFFSET_OF_OBJECT_MEMBER(Method, access_flags_), new_access_flags, false);
+    SetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, access_flags_), new_access_flags, false);
   }
 
   // Approximate what kind of method call would be used for this method.
@@ -598,19 +599,19 @@
   }
 
   void SetMethodIndex(uint16_t new_method_index) {
-    SetField32(OFFSET_OF_OBJECT_MEMBER(Method, method_index_), new_method_index, false);
+    SetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, method_index_), new_method_index, false);
   }
 
   static MemberOffset MethodIndexOffset() {
-    return OFFSET_OF_OBJECT_MEMBER(Method, method_index_);
+    return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, method_index_);
   }
 
   uint32_t GetCodeItemOffset() const {
-    return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, code_item_offset_), false);
+    return GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, code_item_offset_), false);
   }
 
   void SetCodeItemOffset(uint32_t new_code_off) {
-    SetField32(OFFSET_OF_OBJECT_MEMBER(Method, code_item_offset_), new_code_off, false);
+    SetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, code_item_offset_), new_code_off, false);
   }
 
   // Number of 32bit registers that would be required to hold all the arguments
@@ -619,31 +620,31 @@
   uint32_t GetDexMethodIndex() const;
 
   void SetDexMethodIndex(uint32_t new_idx) {
-    SetField32(OFFSET_OF_OBJECT_MEMBER(Method, method_dex_index_), new_idx, false);
+    SetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, method_dex_index_), new_idx, false);
   }
 
   ObjectArray<String>* GetDexCacheStrings() const;
   void SetDexCacheStrings(ObjectArray<String>* new_dex_cache_strings);
 
   static MemberOffset DexCacheStringsOffset() {
-    return OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_strings_);
+    return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_strings_);
   }
 
   static MemberOffset DexCacheResolvedMethodsOffset() {
-    return OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_methods_);
+    return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_resolved_methods_);
   }
 
   static MemberOffset DexCacheResolvedTypesOffset() {
-    return OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_types_);
+    return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_resolved_types_);
   }
 
   static MemberOffset DexCacheInitializedStaticStorageOffset() {
-    return OFFSET_OF_OBJECT_MEMBER(Method,
+    return OFFSET_OF_OBJECT_MEMBER(AbstractMethod,
         dex_cache_initialized_static_storage_);
   }
 
-  ObjectArray<Method>* GetDexCacheResolvedMethods() const;
-  void SetDexCacheResolvedMethods(ObjectArray<Method>* new_dex_cache_methods);
+  ObjectArray<AbstractMethod>* GetDexCacheResolvedMethods() const;
+  void SetDexCacheResolvedMethods(ObjectArray<AbstractMethod>* new_dex_cache_methods);
 
   ObjectArray<Class>* GetDexCacheResolvedTypes() const;
   void SetDexCacheResolvedTypes(ObjectArray<Class>* new_dex_cache_types);
@@ -652,17 +653,17 @@
   void SetDexCacheInitializedStaticStorage(ObjectArray<StaticStorageBase>* new_value);
 
   // Find the method that this method overrides
-  Method* FindOverriddenMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  AbstractMethod* FindOverriddenMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void Invoke(Thread* self, Object* receiver, JValue* args, JValue* result) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   const void* GetCode() const {
-    return GetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(Method, code_), false);
+    return GetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, code_), false);
   }
 
   void SetCode(const void* code) {
-    SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(Method, code_), code, false);
+    SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, code_), code, false);
   }
 
   uint32_t GetCodeSize() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -704,7 +705,7 @@
   }
 
   static MemberOffset GetCodeOffset() {
-    return OFFSET_OF_OBJECT_MEMBER(Method, code_);
+    return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, code_);
   }
 
   const uint32_t* GetMappingTable() const {
@@ -724,11 +725,11 @@
   }
 
   const uint32_t* GetMappingTableRaw() const {
-    return GetFieldPtr<const uint32_t*>(OFFSET_OF_OBJECT_MEMBER(Method, mapping_table_), false);
+    return GetFieldPtr<const uint32_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, mapping_table_), false);
   }
 
   void SetMappingTable(const uint32_t* mapping_table) {
-    SetFieldPtr<const uint32_t*>(OFFSET_OF_OBJECT_MEMBER(Method, mapping_table_),
+    SetFieldPtr<const uint32_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, mapping_table_),
                                  mapping_table, false);
   }
 
@@ -744,11 +745,11 @@
 
   // Callers should wrap the uint16_t* in a VmapTable instance for convenient access.
   const uint16_t* GetVmapTableRaw() const {
-    return GetFieldPtr<const uint16_t*>(OFFSET_OF_OBJECT_MEMBER(Method, vmap_table_), false);
+    return GetFieldPtr<const uint16_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, vmap_table_), false);
   }
 
   void SetVmapTable(const uint16_t* vmap_table) {
-    SetFieldPtr<const uint16_t*>(OFFSET_OF_OBJECT_MEMBER(Method, vmap_table_), vmap_table, false);
+    SetFieldPtr<const uint16_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, vmap_table_), vmap_table, false);
   }
 
   uint32_t GetOatVmapTableOffset() const {
@@ -762,10 +763,11 @@
   }
 
   const uint8_t* GetNativeGcMap() const {
-    return GetFieldPtr<uint8_t*>(OFFSET_OF_OBJECT_MEMBER(Method, native_gc_map_), false);
+    return GetFieldPtr<uint8_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_gc_map_), false);
   }
   void SetNativeGcMap(const uint8_t* data) {
-    SetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(Method, native_gc_map_), data, false);
+    SetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_gc_map_), data,
+        false);
   }
 
   // When building the oat need a convenient place to stuff the offset of the native GC map.
@@ -781,14 +783,14 @@
 
   size_t GetFrameSizeInBytes() const {
     DCHECK_EQ(sizeof(size_t), sizeof(uint32_t));
-    size_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(Method, frame_size_in_bytes_), false);
+    size_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, frame_size_in_bytes_), false);
     DCHECK_LE(static_cast<size_t>(kStackAlignment), result);
     return result;
   }
 
   void SetFrameSizeInBytes(size_t new_frame_size_in_bytes) {
     DCHECK_EQ(sizeof(size_t), sizeof(uint32_t));
-    SetField32(OFFSET_OF_OBJECT_MEMBER(Method, frame_size_in_bytes_),
+    SetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, frame_size_in_bytes_),
                new_frame_size_in_bytes, false);
   }
 
@@ -804,7 +806,7 @@
   void UnregisterNative(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static MemberOffset NativeMethodOffset() {
-    return OFFSET_OF_OBJECT_MEMBER(Method, native_method_);
+    return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_method_);
   }
 
   const void* GetNativeMethod() const {
@@ -814,13 +816,13 @@
   // Native to managed invocation stub entry point
   InvokeStub* GetInvokeStub() const {
     InvokeStub* result = GetFieldPtr<InvokeStub*>(
-        OFFSET_OF_OBJECT_MEMBER(Method, invoke_stub_), false);
+        OFFSET_OF_OBJECT_MEMBER(AbstractMethod, invoke_stub_), false);
     // TODO: DCHECK(result != NULL);  should be ahead of time compiled
     return result;
   }
 
   void SetInvokeStub(InvokeStub* invoke_stub) {
-    SetFieldPtr<InvokeStub*>(OFFSET_OF_OBJECT_MEMBER(Method, invoke_stub_),
+    SetFieldPtr<InvokeStub*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, invoke_stub_),
                              invoke_stub, false);
   }
 
@@ -845,29 +847,29 @@
   }
 
   static MemberOffset GetInvokeStubOffset() {
-    return OFFSET_OF_OBJECT_MEMBER(Method, invoke_stub_);
+    return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, invoke_stub_);
   }
 
   static MemberOffset GetMethodIndexOffset() {
-    return OFFSET_OF_OBJECT_MEMBER(Method, method_index_);
+    return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, method_index_);
   }
 
   uint32_t GetCoreSpillMask() const {
-    return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, core_spill_mask_), false);
+    return GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, core_spill_mask_), false);
   }
 
   void SetCoreSpillMask(uint32_t core_spill_mask) {
     // Computed during compilation
-    SetField32(OFFSET_OF_OBJECT_MEMBER(Method, core_spill_mask_), core_spill_mask, false);
+    SetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, core_spill_mask_), core_spill_mask, false);
   }
 
   uint32_t GetFpSpillMask() const {
-    return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, fp_spill_mask_), false);
+    return GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, fp_spill_mask_), false);
   }
 
   void SetFpSpillMask(uint32_t fp_spill_mask) {
     // Computed during compilation
-    SetField32(OFFSET_OF_OBJECT_MEMBER(Method, fp_spill_mask_), fp_spill_mask, false);
+    SetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, fp_spill_mask_), fp_spill_mask, false);
   }
 
   // Is this a CalleSaveMethod or ResolutionMethod and therefore doesn't adhere to normal
@@ -923,7 +925,7 @@
 
   static void ResetClasses();
 
- private:
+ protected:
   // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
   // The class we are a part of
   Class* declaring_class_;
@@ -991,8 +993,18 @@
   static Class* java_lang_reflect_Method_;
 
   friend class ImageWriter;  // for relocating code_ and invoke_stub_
+  friend struct AbstractMethodOffsets;  // for verifying offset information
+  friend struct ConstructorMethodOffsets;  // for verifying offset information
   friend struct MethodOffsets;  // for verifying offset information
-  DISALLOW_IMPLICIT_CONSTRUCTORS(Method);
+  DISALLOW_IMPLICIT_CONSTRUCTORS(AbstractMethod);
+};
+
+class MANAGED Method : public AbstractMethod {
+
+};
+
+class MANAGED Constructor : public AbstractMethod {
+
 };
 
 class MANAGED Array : public Object {
@@ -1536,29 +1548,29 @@
 
   void SetDexCache(DexCache* new_dex_cache);
 
-  ObjectArray<Method>* GetDirectMethods() const {
+  ObjectArray<AbstractMethod>* GetDirectMethods() const {
     DCHECK(IsLoaded() || IsErroneous());
-    return GetFieldObject<ObjectArray<Method>*>(
+    return GetFieldObject<ObjectArray<AbstractMethod>*>(
         OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false);
   }
 
-  void SetDirectMethods(ObjectArray<Method>* new_direct_methods) {
-    DCHECK(NULL == GetFieldObject<ObjectArray<Method>*>(
+  void SetDirectMethods(ObjectArray<AbstractMethod>* new_direct_methods) {
+    DCHECK(NULL == GetFieldObject<ObjectArray<AbstractMethod>*>(
         OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false));
     DCHECK_NE(0, new_direct_methods->GetLength());
     SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_),
                    new_direct_methods, false);
   }
 
-  Method* GetDirectMethod(int32_t i) const
+  AbstractMethod* GetDirectMethod(int32_t i) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     return GetDirectMethods()->Get(i);
   }
 
-  void SetDirectMethod(uint32_t i, Method* f)  // TODO: uint16_t
+  void SetDirectMethod(uint32_t i, AbstractMethod* f)  // TODO: uint16_t
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_){
-    ObjectArray<Method>* direct_methods =
-        GetFieldObject<ObjectArray<Method>*>(
+    ObjectArray<AbstractMethod>* direct_methods =
+        GetFieldObject<ObjectArray<AbstractMethod>*>(
             OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false);
     direct_methods->Set(i, f);
   }
@@ -1568,13 +1580,13 @@
     return (GetDirectMethods() != NULL) ? GetDirectMethods()->GetLength() : 0;
   }
 
-  ObjectArray<Method>* GetVirtualMethods() const {
+  ObjectArray<AbstractMethod>* GetVirtualMethods() const {
     DCHECK(IsLoaded() || IsErroneous());
-    return GetFieldObject<ObjectArray<Method>*>(
+    return GetFieldObject<ObjectArray<AbstractMethod>*>(
         OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_), false);
   }
 
-  void SetVirtualMethods(ObjectArray<Method>* new_virtual_methods) {
+  void SetVirtualMethods(ObjectArray<AbstractMethod>* new_virtual_methods) {
     // TODO: we reassign virtual methods to grow the table for miranda
     // methods.. they should really just be assigned once
     DCHECK_NE(0, new_virtual_methods->GetLength());
@@ -1587,37 +1599,37 @@
     return (GetVirtualMethods() != NULL) ? GetVirtualMethods()->GetLength() : 0;
   }
 
-  Method* GetVirtualMethod(uint32_t i) const
+  AbstractMethod* GetVirtualMethod(uint32_t i) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     DCHECK(IsResolved() || IsErroneous());
     return GetVirtualMethods()->Get(i);
   }
 
-  Method* GetVirtualMethodDuringLinking(uint32_t i) const
+  AbstractMethod* GetVirtualMethodDuringLinking(uint32_t i) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     DCHECK(IsLoaded() || IsErroneous());
     return GetVirtualMethods()->Get(i);
   }
 
-  void SetVirtualMethod(uint32_t i, Method* f)  // TODO: uint16_t
+  void SetVirtualMethod(uint32_t i, AbstractMethod* f)  // TODO: uint16_t
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    ObjectArray<Method>* virtual_methods =
-        GetFieldObject<ObjectArray<Method>*>(
+    ObjectArray<AbstractMethod>* virtual_methods =
+        GetFieldObject<ObjectArray<AbstractMethod>*>(
             OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_), false);
     virtual_methods->Set(i, f);
   }
 
-  ObjectArray<Method>* GetVTable() const {
+  ObjectArray<AbstractMethod>* GetVTable() const {
     DCHECK(IsResolved() || IsErroneous());
-    return GetFieldObject<ObjectArray<Method>*>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false);
+    return GetFieldObject<ObjectArray<AbstractMethod>*>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false);
   }
 
-  ObjectArray<Method>* GetVTableDuringLinking() const {
+  ObjectArray<AbstractMethod>* GetVTableDuringLinking() const {
     DCHECK(IsLoaded() || IsErroneous());
-    return GetFieldObject<ObjectArray<Method>*>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false);
+    return GetFieldObject<ObjectArray<AbstractMethod>*>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false);
   }
 
-  void SetVTable(ObjectArray<Method>* new_vtable) {
+  void SetVTable(ObjectArray<AbstractMethod>* new_vtable) {
     SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), new_vtable, false);
   }
 
@@ -1628,7 +1640,7 @@
   // Given a method implemented by this class but potentially from a
   // super class, return the specific implementation
   // method for this class.
-  Method* FindVirtualMethodForVirtual(Method* method)
+  AbstractMethod* FindVirtualMethodForVirtual(AbstractMethod* method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     DCHECK(!method->GetDeclaringClass()->IsInterface());
     // The argument method may from a super class.
@@ -1639,16 +1651,16 @@
   // Given a method implemented by this class, but potentially from a
   // super class or interface, return the specific implementation
   // method for this class.
-  Method* FindVirtualMethodForInterface(Method* method)
+  AbstractMethod* FindVirtualMethodForInterface(AbstractMethod* method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  Method* FindInterfaceMethod(const StringPiece& name, const StringPiece& descriptor) const
+  AbstractMethod* FindInterfaceMethod(const StringPiece& name, const StringPiece& descriptor) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  Method* FindInterfaceMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const
+  AbstractMethod* FindInterfaceMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  Method* FindVirtualMethodForVirtualOrInterface(Method* method)
+  AbstractMethod* FindVirtualMethodForVirtualOrInterface(AbstractMethod* method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     if (method->IsDirect()) {
       return method;
@@ -1659,28 +1671,28 @@
     return FindVirtualMethodForVirtual(method);
   }
 
-  Method* FindDeclaredVirtualMethod(const StringPiece& name, const StringPiece& signature) const
+  AbstractMethod* FindDeclaredVirtualMethod(const StringPiece& name, const StringPiece& signature) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  Method* FindDeclaredVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const
+  AbstractMethod* FindDeclaredVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  Method* FindVirtualMethod(const StringPiece& name, const StringPiece& descriptor) const
+  AbstractMethod* FindVirtualMethod(const StringPiece& name, const StringPiece& descriptor) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  Method* FindVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const
+  AbstractMethod* FindVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  Method* FindDeclaredDirectMethod(const StringPiece& name, const StringPiece& signature) const
+  AbstractMethod* FindDeclaredDirectMethod(const StringPiece& name, const StringPiece& signature) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  Method* FindDeclaredDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const
+  AbstractMethod* FindDeclaredDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  Method* FindDirectMethod(const StringPiece& name, const StringPiece& signature) const
+  AbstractMethod* FindDirectMethod(const StringPiece& name, const StringPiece& signature) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  Method* FindDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const
+  AbstractMethod* FindDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   int32_t GetIfTableCount() const {
@@ -1894,7 +1906,7 @@
   DexCache* dex_cache_;
 
   // static, private, and <init> methods
-  ObjectArray<Method>* direct_methods_;
+  ObjectArray<AbstractMethod>* direct_methods_;
 
   // instance fields
   //
@@ -1936,13 +1948,13 @@
   Class* verify_error_class_;
 
   // virtual methods defined in this class; invoked through vtable
-  ObjectArray<Method>* virtual_methods_;
+  ObjectArray<AbstractMethod>* virtual_methods_;
 
   // Virtual method table (vtable), for use by "invoke-virtual".  The vtable from the superclass is
   // copied in, and virtual methods from our class either replace those from the super or are
   // appended. For abstract classes, methods may be created in the vtable that aren't in
   // virtual_ methods_ for miranda methods.
-  ObjectArray<Method>* vtable_;
+  ObjectArray<AbstractMethod>* vtable_;
 
   // access flags; low 16 bits are defined by VM spec
   uint32_t access_flags_;
@@ -2043,7 +2055,9 @@
 
 inline bool Object::IsMethod() const {
   Class* c = GetClass();
-  return c == Method::GetMethodClass() || c == Method::GetConstructorClass();
+  return
+      c == AbstractMethod::GetMethodClass() ||
+      c == AbstractMethod::GetConstructorClass();
 }
 
 inline bool Object::IsReferenceInstance() const {
@@ -2076,7 +2090,7 @@
     result = GetClass()->GetObjectSize();
   }
   DCHECK(!IsField()  || result == sizeof(Field));
-  DCHECK(!IsMethod() || result == sizeof(Method));
+  DCHECK(!IsMethod() || result == sizeof(AbstractMethod));
   return result;
 }
 
@@ -2091,15 +2105,15 @@
   SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Field, declaring_class_), new_declaring_class, false);
 }
 
-inline Class* Method::GetDeclaringClass() const {
-  Class* result = GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Method, declaring_class_), false);
+inline Class* AbstractMethod::GetDeclaringClass() const {
+  Class* result = GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, declaring_class_), false);
   DCHECK(result != NULL) << this;
   DCHECK(result->IsIdxLoaded() || result->IsErroneous()) << this;
   return result;
 }
 
-inline void Method::SetDeclaringClass(Class *new_declaring_class) {
-  SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, declaring_class_), new_declaring_class, false);
+inline void AbstractMethod::SetDeclaringClass(Class *new_declaring_class) {
+  SetFieldObject(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, declaring_class_), new_declaring_class, false);
 }
 
 inline size_t Array::SizeOf() const {
@@ -2421,27 +2435,27 @@
   DCHECK(IsLoaded() || IsErroneous() ||
       this == String::GetJavaLangString() ||
       this == Field::GetJavaLangReflectField() ||
-      this == Method::GetConstructorClass() ||
-      this == Method::GetMethodClass());
+      this == AbstractMethod::GetConstructorClass() ||
+      this == AbstractMethod::GetMethodClass());
   return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), false);
 }
 
-inline uint32_t Method::GetAccessFlags() const {
+inline uint32_t AbstractMethod::GetAccessFlags() const {
   DCHECK(GetDeclaringClass()->IsIdxLoaded() || GetDeclaringClass()->IsErroneous());
-  return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, access_flags_), false);
+  return GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, access_flags_), false);
 }
 
-inline uint16_t Method::GetMethodIndex() const {
+inline uint16_t AbstractMethod::GetMethodIndex() const {
   DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous());
-  return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, method_index_), false);
+  return GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, method_index_), false);
 }
 
-inline uint32_t Method::GetDexMethodIndex() const {
+inline uint32_t AbstractMethod::GetDexMethodIndex() const {
   DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
-  return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, method_dex_index_), false);
+  return GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, method_dex_index_), false);
 }
 
-inline bool Method::CheckIncompatibleClassChange(InvokeType type) {
+inline bool AbstractMethod::CheckIncompatibleClassChange(InvokeType type) {
   switch (type) {
     case kStatic:
       return !IsStatic();
@@ -2463,7 +2477,7 @@
   }
 }
 
-inline void Method::AssertPcIsWithinCode(uintptr_t pc) const {
+inline void AbstractMethod::AssertPcIsWithinCode(uintptr_t pc) const {
   if (!kIsDebugBuild) {
     return;
   }
@@ -2599,21 +2613,21 @@
   }
 
   size_t GetMethodArrayCount() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    ObjectArray<Method>* method_array = down_cast<ObjectArray<Method>*>(Get(kMethodArray));
+    ObjectArray<AbstractMethod>* method_array = down_cast<ObjectArray<AbstractMethod>*>(Get(kMethodArray));
     if (method_array == NULL) {
       return 0;
     }
     return method_array->GetLength();
   }
 
-  ObjectArray<Method>* GetMethodArray() const
+  ObjectArray<AbstractMethod>* GetMethodArray() const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    ObjectArray<Method>* method_array = down_cast<ObjectArray<Method>*>(Get(kMethodArray));
+    ObjectArray<AbstractMethod>* method_array = down_cast<ObjectArray<AbstractMethod>*>(Get(kMethodArray));
     DCHECK(method_array != NULL);
     return method_array;
   }
 
-  void SetMethodArray(ObjectArray<Method>* new_ma)
+  void SetMethodArray(ObjectArray<AbstractMethod>* new_ma)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     DCHECK(new_ma != NULL);
     DCHECK(Get(kMethodArray) == NULL);
diff --git a/src/object_test.cc b/src/object_test.cc
index 081be4b..3dfa0a9 100644
--- a/src/object_test.cc
+++ b/src/object_test.cc
@@ -190,7 +190,7 @@
   // pretend we are trying to call 'new char[3]' from String.toCharArray
   ScopedObjectAccess soa(Thread::Current());
   Class* java_util_Arrays = class_linker_->FindSystemClass("Ljava/util/Arrays;");
-  Method* sort = java_util_Arrays->FindDirectMethod("sort", "([I)V");
+  AbstractMethod* sort = java_util_Arrays->FindDirectMethod("sort", "([I)V");
   const DexFile::StringId* string_id = java_lang_dex_file_->FindStringId("[I");
   ASSERT_TRUE(string_id != NULL);
   const DexFile::TypeId* type_id = java_lang_dex_file_->FindTypeId(
@@ -213,7 +213,7 @@
 
   Class* klass =
       class_linker_->FindClass("LStaticsFromCode;", soa.Decode<ClassLoader*>(class_loader));
-  Method* clinit = klass->FindDirectMethod("<clinit>", "()V");
+  AbstractMethod* clinit = klass->FindDirectMethod("<clinit>", "()V");
   const DexFile::StringId* klass_string_id = dex_file->FindStringId("LStaticsFromCode;");
   ASSERT_TRUE(klass_string_id != NULL);
   const DexFile::TypeId* klass_type_id = dex_file->FindTypeId(
@@ -331,29 +331,29 @@
   Class* klass2 = linker->FindClass("LProtoCompare2;", class_loader_2.get());
   ASSERT_TRUE(klass2 != NULL);
 
-  Method* m1_1 = klass1->GetVirtualMethod(0);
+  AbstractMethod* m1_1 = klass1->GetVirtualMethod(0);
   MethodHelper mh(m1_1);
   EXPECT_STREQ(mh.GetName(), "m1");
-  Method* m2_1 = klass1->GetVirtualMethod(1);
+  AbstractMethod* m2_1 = klass1->GetVirtualMethod(1);
   mh.ChangeMethod(m2_1);
   EXPECT_STREQ(mh.GetName(), "m2");
-  Method* m3_1 = klass1->GetVirtualMethod(2);
+  AbstractMethod* m3_1 = klass1->GetVirtualMethod(2);
   mh.ChangeMethod(m3_1);
   EXPECT_STREQ(mh.GetName(), "m3");
-  Method* m4_1 = klass1->GetVirtualMethod(3);
+  AbstractMethod* m4_1 = klass1->GetVirtualMethod(3);
   mh.ChangeMethod(m4_1);
   EXPECT_STREQ(mh.GetName(), "m4");
 
-  Method* m1_2 = klass2->GetVirtualMethod(0);
+  AbstractMethod* m1_2 = klass2->GetVirtualMethod(0);
   mh.ChangeMethod(m1_2);
   EXPECT_STREQ(mh.GetName(), "m1");
-  Method* m2_2 = klass2->GetVirtualMethod(1);
+  AbstractMethod* m2_2 = klass2->GetVirtualMethod(1);
   mh.ChangeMethod(m2_2);
   EXPECT_STREQ(mh.GetName(), "m2");
-  Method* m3_2 = klass2->GetVirtualMethod(2);
+  AbstractMethod* m3_2 = klass2->GetVirtualMethod(2);
   mh.ChangeMethod(m3_2);
   EXPECT_STREQ(mh.GetName(), "m3");
-  Method* m4_2 = klass2->GetVirtualMethod(3);
+  AbstractMethod* m4_2 = klass2->GetVirtualMethod(3);
   mh.ChangeMethod(m4_2);
   EXPECT_STREQ(mh.GetName(), "m4");
 
diff --git a/src/object_utils.h b/src/object_utils.h
index f6158f3..035f689 100644
--- a/src/object_utils.h
+++ b/src/object_utils.h
@@ -199,13 +199,10 @@
   }
 
   const DexFile& GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    const DexFile* result = dex_file_;
-    if (result == NULL) {
-      const DexCache* dex_cache = GetDexCache();
-      result = &GetClassLinker()->FindDexFile(dex_cache);
-      dex_file_ = result;
+    if (dex_file_ == NULL) {
+      dex_file_ = GetDexCache()->GetDexFile();
     }
-    return *result;
+    return *dex_file_;
   }
 
   DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -366,13 +363,10 @@
     return result;
   }
   const DexFile& GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    const DexFile* result = dex_file_;
-    if (result == NULL) {
-      const DexCache* dex_cache = GetDexCache();
-      result = &GetClassLinker()->FindDexFile(dex_cache);
-      dex_file_ = result;
+    if (dex_file_ == NULL) {
+      dex_file_ = GetDexCache()->GetDexFile();
     }
-    return *result;
+    return *dex_file_;
   }
 
   ClassLinker* class_linker_;
@@ -390,21 +384,21 @@
      : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), method_(NULL), shorty_(NULL),
        shorty_len_(0) {}
 
-  explicit MethodHelper(const Method* m)
+  explicit MethodHelper(const AbstractMethod* m)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
       : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), method_(NULL), shorty_(NULL),
         shorty_len_(0) {
     SetMethod(m);
   }
 
-  MethodHelper(const Method* m, ClassLinker* l)
+  MethodHelper(const AbstractMethod* m, ClassLinker* l)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
       : class_linker_(l), dex_cache_(NULL), dex_file_(NULL), method_(NULL), shorty_(NULL),
         shorty_len_(0) {
     SetMethod(m);
   }
 
-  void ChangeMethod(Method* new_m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  void ChangeMethod(AbstractMethod* new_m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     DCHECK(new_m != NULL);
     if (dex_cache_ != NULL) {
       Class* klass = new_m->GetDeclaringClass();
@@ -675,12 +669,12 @@
  private:
   // Set the method_ field, for proxy methods looking up the interface method via the resolved
   // methods table.
-  void SetMethod(const Method* method)
+  void SetMethod(const AbstractMethod* method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     if (method != NULL) {
       Class* klass = method->GetDeclaringClass();
       if (klass->IsProxyClass()) {
-        Method* interface_method =
+        AbstractMethod* interface_method =
             method->GetDexCacheResolvedMethods()->Get(method->GetDexMethodIndex());
         CHECK(interface_method != NULL);
         CHECK(interface_method == GetClassLinker()->FindMethodForProxy(klass, method));
@@ -702,7 +696,7 @@
   ClassLinker* class_linker_;
   DexCache* dex_cache_;
   const DexFile* dex_file_;
-  const Method* method_;
+  const AbstractMethod* method_;
   const char* shorty_;
   uint32_t shorty_len_;
 
diff --git a/src/reflection.cc b/src/reflection.cc
index 7f1d4d1..7d73ae2 100644
--- a/src/reflection.cc
+++ b/src/reflection.cc
@@ -28,7 +28,7 @@
 jobject InvokeMethod(const ScopedObjectAccess& soa, jobject javaMethod, jobject javaReceiver,
                      jobject javaArgs) {
   jmethodID mid = soa.Env()->FromReflectedMethod(javaMethod);
-  Method* m = soa.DecodeMethod(mid);
+  AbstractMethod* m = soa.DecodeMethod(mid);
 
   Class* declaring_class = m->GetDeclaringClass();
   if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(declaring_class, true, true)) {
@@ -243,7 +243,7 @@
   soa.DecodeMethod(m)->Invoke(soa.Self(), NULL, args, &value);
 }
 
-static std::string UnboxingFailureKind(Method* m, int index, Field* f)
+static std::string UnboxingFailureKind(AbstractMethod* m, int index, Field* f)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   if (m != NULL && index != -1) {
     ++index; // Humans count from 1.
@@ -255,7 +255,7 @@
   return "result";
 }
 
-static bool UnboxPrimitive(Object* o, Class* dst_class, JValue& unboxed_value, Method* m,
+static bool UnboxPrimitive(Object* o, Class* dst_class, JValue& unboxed_value, AbstractMethod* m,
                            int index, Field* f)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   if (!dst_class->IsPrimitive()) {
@@ -326,7 +326,7 @@
                                boxed_value, unboxed_value);
 }
 
-bool UnboxPrimitiveForArgument(Object* o, Class* dst_class, JValue& unboxed_value, Method* m, size_t index) {
+bool UnboxPrimitiveForArgument(Object* o, Class* dst_class, JValue& unboxed_value, AbstractMethod* m, size_t index) {
   CHECK(m != NULL);
   return UnboxPrimitive(o, dst_class, unboxed_value, m, index, NULL);
 }
diff --git a/src/reflection.h b/src/reflection.h
index 93219f8..b61acda 100644
--- a/src/reflection.h
+++ b/src/reflection.h
@@ -25,13 +25,13 @@
 class Class;
 class Field;
 union JValue;
-class Method;
+class AbstractMethod;
 class Object;
 class ScopedObjectAccess;
 
 void BoxPrimitive(Primitive::Type src_class, JValue& value)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-bool UnboxPrimitiveForArgument(Object* o, Class* dst_class, JValue& unboxed_value, Method* m,
+bool UnboxPrimitiveForArgument(Object* o, Class* dst_class, JValue& unboxed_value, AbstractMethod* m,
                                size_t index)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 bool UnboxPrimitiveForField(Object* o, Class* dst_class, JValue& unboxed_value, Field* f)
diff --git a/src/runtime.cc b/src/runtime.cc
index f37788d..8262f8a 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -556,7 +556,7 @@
   Class* class_loader_class = soa.Decode<Class*>(WellKnownClasses::java_lang_ClassLoader);
   CHECK(Runtime::Current()->GetClassLinker()->EnsureInitialized(class_loader_class, true, true));
 
-  Method* getSystemClassLoader = class_loader_class->FindDirectMethod("getSystemClassLoader", "()Ljava/lang/ClassLoader;");
+  AbstractMethod* getSystemClassLoader = class_loader_class->FindDirectMethod("getSystemClassLoader", "()Ljava/lang/ClassLoader;");
   CHECK(getSystemClassLoader != NULL);
 
   ClassLoader* class_loader =
@@ -960,9 +960,9 @@
   resolution_stub_array_[type] = resolution_stub_array;
 }
 
-Method* Runtime::CreateResolutionMethod() {
-  Class* method_class = Method::GetMethodClass();
-  SirtRef<Method> method(down_cast<Method*>(method_class->AllocObject()));
+AbstractMethod* Runtime::CreateResolutionMethod() {
+  Class* method_class = AbstractMethod::GetMethodClass();
+  SirtRef<AbstractMethod> method(down_cast<AbstractMethod*>(method_class->AllocObject()));
   method->SetDeclaringClass(method_class);
   // TODO: use a special method for resolution method saves
   method->SetDexMethodIndex(DexFile::kDexNoIndex16);
@@ -972,9 +972,9 @@
   return method.get();
 }
 
-Method* Runtime::CreateCalleeSaveMethod(InstructionSet instruction_set, CalleeSaveType type) {
-  Class* method_class = Method::GetMethodClass();
-  SirtRef<Method> method(down_cast<Method*>(method_class->AllocObject()));
+AbstractMethod* Runtime::CreateCalleeSaveMethod(InstructionSet instruction_set, CalleeSaveType type) {
+  Class* method_class = AbstractMethod::GetMethodClass();
+  SirtRef<AbstractMethod> method(down_cast<AbstractMethod*>(method_class->AllocObject()));
   method->SetDeclaringClass(method_class);
   // TODO: use a special method for callee saves
   method->SetDexMethodIndex(DexFile::kDexNoIndex16);
@@ -1046,7 +1046,7 @@
   return method.get();
 }
 
-void Runtime::SetCalleeSaveMethod(Method* method, CalleeSaveType type) {
+void Runtime::SetCalleeSaveMethod(AbstractMethod* method, CalleeSaveType type) {
   DCHECK_LT(static_cast<int>(type), static_cast<int>(kLastCalleeSaveType));
   callee_save_methods_[type] = method;
 }
diff --git a/src/runtime.h b/src/runtime.h
index 4dcefb5..5f277a1 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -48,7 +48,7 @@
 class Heap;
 class InternTable;
 struct JavaVMExt;
-class Method;
+class AbstractMethod;
 class MonitorList;
 class SignalCatcher;
 class String;
@@ -254,7 +254,7 @@
   void SetResolutionStubArray(ByteArray* resolution_stub_array, TrampolineType type);
 
   // Returns a special method that calls into a trampoline for runtime method resolution
-  Method* GetResolutionMethod() const {
+  AbstractMethod* GetResolutionMethod() const {
     CHECK(HasResolutionMethod());
     return resolution_method_;
   }
@@ -263,11 +263,11 @@
     return resolution_method_ != NULL;
   }
 
-  void SetResolutionMethod(Method* method) {
+  void SetResolutionMethod(AbstractMethod* method) {
     resolution_method_ = method;
   }
 
-  Method* CreateResolutionMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  AbstractMethod* CreateResolutionMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Returns a special method that describes all callee saves being spilled to the stack.
   enum CalleeSaveType {
@@ -281,20 +281,20 @@
     return callee_save_methods_[type] != NULL;
   }
 
-  Method* GetCalleeSaveMethod(CalleeSaveType type) const {
+  AbstractMethod* GetCalleeSaveMethod(CalleeSaveType type) const {
     CHECK(HasCalleeSaveMethod(type));
     return callee_save_methods_[type];
   }
 
-  void SetCalleeSaveMethod(Method* method, CalleeSaveType type);
+  void SetCalleeSaveMethod(AbstractMethod* method, CalleeSaveType type);
 
-  Method* CreateCalleeSaveMethod(InstructionSet instruction_set, CalleeSaveType type)
+  AbstractMethod* CreateCalleeSaveMethod(InstructionSet instruction_set, CalleeSaveType type)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  Method* CreateRefOnlyCalleeSaveMethod(InstructionSet instruction_set)
+  AbstractMethod* CreateRefOnlyCalleeSaveMethod(InstructionSet instruction_set)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  Method* CreateRefAndArgsCalleeSaveMethod(InstructionSet instruction_set)
+  AbstractMethod* CreateRefAndArgsCalleeSaveMethod(InstructionSet instruction_set)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   int32_t GetStat(int kind);
@@ -398,9 +398,9 @@
 
   ByteArray* resolution_stub_array_[kLastTrampolineMethodType];
 
-  Method* callee_save_methods_[kLastCalleeSaveType];
+  AbstractMethod* callee_save_methods_[kLastCalleeSaveType];
 
-  Method* resolution_method_;
+  AbstractMethod* resolution_method_;
 
   // As returned by ClassLoader.getSystemClassLoader()
   ClassLoader* system_class_loader_;
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 01bdf9a..4af6fe5 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -90,7 +90,7 @@
 namespace art {
 
 // Helper function to allocate array for FILLED_NEW_ARRAY.
-Array* CheckAndAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count,
+Array* CheckAndAllocArrayFromCode(uint32_t type_idx, AbstractMethod* method, int32_t component_count,
                                   Thread* self, bool access_check) {
   if (UNLIKELY(component_count < 0)) {
     self->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", component_count);
@@ -128,7 +128,7 @@
   }
 }
 
-Field* FindFieldFromCode(uint32_t field_idx, const Method* referrer, Thread* self,
+Field* FindFieldFromCode(uint32_t field_idx, const AbstractMethod* referrer, Thread* self,
                          FindFieldType type, size_t expected_size) {
   bool is_primitive;
   bool is_set;
@@ -208,11 +208,11 @@
 }
 
 // Slow path method resolution
-Method* FindMethodFromCode(uint32_t method_idx, Object* this_object, const Method* referrer,
+AbstractMethod* FindMethodFromCode(uint32_t method_idx, Object* this_object, const AbstractMethod* referrer,
                            Thread* self, bool access_check, InvokeType type) {
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   bool is_direct = type == kStatic || type == kDirect;
-  Method* resolved_method = class_linker->ResolveMethod(method_idx, referrer, type);
+  AbstractMethod* resolved_method = class_linker->ResolveMethod(method_idx, referrer, type);
   if (UNLIKELY(resolved_method == NULL)) {
     DCHECK(self->IsExceptionPending());  // Throw exception and unwind.
     return NULL;  // Failure.
@@ -221,7 +221,7 @@
       if (is_direct) {
         return resolved_method;
       } else if (type == kInterface) {
-        Method* interface_method =
+        AbstractMethod* interface_method =
             this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
         if (UNLIKELY(interface_method == NULL)) {
           ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(resolved_method, this_object,
@@ -231,7 +231,7 @@
           return interface_method;
         }
       } else {
-        ObjectArray<Method>* vtable;
+        ObjectArray<AbstractMethod>* vtable;
         uint16_t vtable_index = resolved_method->GetMethodIndex();
         if (type == kSuper) {
           vtable = referrer->GetDeclaringClass()->GetSuperClass()->GetVTable();
@@ -273,7 +273,7 @@
       if (is_direct) {
         return resolved_method;
       } else if (type == kInterface) {
-        Method* interface_method =
+        AbstractMethod* interface_method =
             this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
         if (UNLIKELY(interface_method == NULL)) {
           ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(resolved_method, this_object,
@@ -283,7 +283,7 @@
           return interface_method;
         }
       } else {
-        ObjectArray<Method>* vtable;
+        ObjectArray<AbstractMethod>* vtable;
         uint16_t vtable_index = resolved_method->GetMethodIndex();
         if (type == kSuper) {
           Class* super_class = referring_class->GetSuperClass();
@@ -310,7 +310,7 @@
   }
 }
 
-Class* ResolveVerifyAndClinit(uint32_t type_idx, const Method* referrer, Thread* self,
+Class* ResolveVerifyAndClinit(uint32_t type_idx, const AbstractMethod* referrer, Thread* self,
                                bool can_run_clinit, bool verify_access) {
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   Class* klass = class_linker->ResolveType(type_idx, referrer);
diff --git a/src/runtime_support.h b/src/runtime_support.h
index 16f0d2e..b4a23ff 100644
--- a/src/runtime_support.h
+++ b/src/runtime_support.h
@@ -41,14 +41,14 @@
 class Array;
 class Class;
 class Field;
-class Method;
+class AbstractMethod;
 class Object;
 
 // Given the context of a calling Method, use its DexCache to resolve a type to a Class. If it
 // cannot be resolved, throw an error. If it can, use it to create an instance.
 // When verification/compiler hasn't been able to verify access, optionally perform an access
 // check.
-static inline Object* AllocObjectFromCode(uint32_t type_idx, Method* method, Thread* self,
+static inline Object* AllocObjectFromCode(uint32_t type_idx, AbstractMethod* method, Thread* self,
                                           bool access_check)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
@@ -83,7 +83,7 @@
 // it cannot be resolved, throw an error. If it can, use it to create an array.
 // When verification/compiler hasn't been able to verify access, optionally perform an access
 // check.
-static inline Array* AllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count,
+static inline Array* AllocArrayFromCode(uint32_t type_idx, AbstractMethod* method, int32_t component_count,
                                         bool access_check)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   if (UNLIKELY(component_count < 0)) {
@@ -110,7 +110,7 @@
   return Array::Alloc(klass, component_count);
 }
 
-extern Array* CheckAndAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count,
+extern Array* CheckAndAllocArrayFromCode(uint32_t type_idx, AbstractMethod* method, int32_t component_count,
                                          Thread* self, bool access_check)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -127,12 +127,12 @@
 };
 
 // Slow field find that can initialize classes and may throw exceptions.
-extern Field* FindFieldFromCode(uint32_t field_idx, const Method* referrer, Thread* self,
+extern Field* FindFieldFromCode(uint32_t field_idx, const AbstractMethod* referrer, Thread* self,
                                 FindFieldType type, size_t expected_size)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 // Fast path field resolution that can't initialize classes or throw exceptions.
-static inline Field* FindFieldFast(uint32_t field_idx, const Method* referrer,
+static inline Field* FindFieldFast(uint32_t field_idx, const AbstractMethod* referrer,
                                    FindFieldType type, size_t expected_size)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   Field* resolved_field = referrer->GetDeclaringClass()->GetDexCache()->GetResolvedField(field_idx);
@@ -181,14 +181,14 @@
 }
 
 // Fast path method resolution that can't throw exceptions.
-static inline Method* FindMethodFast(uint32_t method_idx, Object* this_object,
-                                     const Method* referrer, bool access_check, InvokeType type)
+static inline AbstractMethod* FindMethodFast(uint32_t method_idx, Object* this_object,
+                                     const AbstractMethod* referrer, bool access_check, InvokeType type)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   bool is_direct = type == kStatic || type == kDirect;
   if (UNLIKELY(this_object == NULL && !is_direct)) {
     return NULL;
   }
-  Method* resolved_method =
+  AbstractMethod* resolved_method =
       referrer->GetDeclaringClass()->GetDexCache()->GetResolvedMethod(method_idx);
   if (UNLIKELY(resolved_method == NULL)) {
     return NULL;
@@ -221,15 +221,15 @@
   }
 }
 
-extern Method* FindMethodFromCode(uint32_t method_idx, Object* this_object, const Method* referrer,
+extern AbstractMethod* FindMethodFromCode(uint32_t method_idx, Object* this_object, const AbstractMethod* referrer,
                                   Thread* self, bool access_check, InvokeType type)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-extern Class* ResolveVerifyAndClinit(uint32_t type_idx, const Method* referrer, Thread* self,
+extern Class* ResolveVerifyAndClinit(uint32_t type_idx, const AbstractMethod* referrer, Thread* self,
                                      bool can_run_clinit, bool verify_access)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-static inline String* ResolveStringFromCode(const Method* referrer, uint32_t string_idx)
+static inline String* ResolveStringFromCode(const AbstractMethod* referrer, uint32_t string_idx)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   return class_linker->ResolveString(string_idx, referrer);
@@ -268,7 +268,7 @@
               PrettyMethod(self->GetCurrentMethod()).c_str());
   }
   // Make sure that the result is an instance of the type this method was expected to return.
-  Method* m = self->GetCurrentMethod();
+  AbstractMethod* m = self->GetCurrentMethod();
   MethodHelper mh(m);
   Class* return_type = mh.GetReturnType();
 
diff --git a/src/scoped_thread_state_change.h b/src/scoped_thread_state_change.h
index 68fbf69..c9b353f 100644
--- a/src/scoped_thread_state_change.h
+++ b/src/scoped_thread_state_change.h
@@ -227,7 +227,7 @@
     return reinterpret_cast<jfieldID>(field);
   }
 
-  Method* DecodeMethod(jmethodID mid) const
+  AbstractMethod* DecodeMethod(jmethodID mid) const
       LOCKS_EXCLUDED(JavaVMExt::globals_lock,
                      JavaVMExt::weak_globals_lock)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -237,10 +237,10 @@
     // TODO: we should make these unique weak globals if Method instances can ever move.
     UNIMPLEMENTED(WARNING);
 #endif
-    return reinterpret_cast<Method*>(mid);
+    return reinterpret_cast<AbstractMethod*>(mid);
   }
 
-  jmethodID EncodeMethod(Method* method) const
+  jmethodID EncodeMethod(AbstractMethod* method) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     Locks::mutator_lock_->AssertSharedHeld();
     DCHECK_EQ(thread_state_, kRunnable);  // Don't work with raw objects in non-runnable states.
diff --git a/src/space.cc b/src/space.cc
index 19e9e5c..f61f872 100644
--- a/src/space.cc
+++ b/src/space.cc
@@ -431,14 +431,14 @@
       down_cast<ByteArray*>(resolution_stub_array), Runtime::kUnknownMethod);
 
   Object* resolution_method = image_header.GetImageRoot(ImageHeader::kResolutionMethod);
-  runtime->SetResolutionMethod(down_cast<Method*>(resolution_method));
+  runtime->SetResolutionMethod(down_cast<AbstractMethod*>(resolution_method));
 
   Object* callee_save_method = image_header.GetImageRoot(ImageHeader::kCalleeSaveMethod);
-  runtime->SetCalleeSaveMethod(down_cast<Method*>(callee_save_method), Runtime::kSaveAll);
+  runtime->SetCalleeSaveMethod(down_cast<AbstractMethod*>(callee_save_method), Runtime::kSaveAll);
   callee_save_method = image_header.GetImageRoot(ImageHeader::kRefsOnlySaveMethod);
-  runtime->SetCalleeSaveMethod(down_cast<Method*>(callee_save_method), Runtime::kRefsOnly);
+  runtime->SetCalleeSaveMethod(down_cast<AbstractMethod*>(callee_save_method), Runtime::kRefsOnly);
   callee_save_method = image_header.GetImageRoot(ImageHeader::kRefsAndArgsSaveMethod);
-  runtime->SetCalleeSaveMethod(down_cast<Method*>(callee_save_method), Runtime::kRefsAndArgs);
+  runtime->SetCalleeSaveMethod(down_cast<AbstractMethod*>(callee_save_method), Runtime::kRefsAndArgs);
 
   ImageSpace* space = new ImageSpace(image_file_name, map.release());
   if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
diff --git a/src/space_bitmap.cc b/src/space_bitmap.cc
index cd07a81..d117c21 100644
--- a/src/space_bitmap.cc
+++ b/src/space_bitmap.cc
@@ -177,7 +177,7 @@
     for (int32_t i = 0; i < fields->GetLength(); i++) {
       Field* field = fields->Get(i);
       FieldHelper fh(field);
-      if (!fh.GetType()->IsPrimitive()) {
+      if (!fh.IsPrimitiveType()) {
         Object* value = field->GetObj(obj);
         if (value != NULL) {
           WalkFieldsInOrder(visited, callback, value,  arg);
@@ -207,7 +207,7 @@
       for (int32_t i = 0; i < fields->GetLength(); i++) {
         Field* field = fields->Get(i);
         FieldHelper fh(field);
-        if (!fh.GetType()->IsPrimitive()) {
+        if (!fh.IsPrimitiveType()) {
           Object* value = field->GetObj(NULL);
           if (value != NULL) {
             WalkFieldsInOrder(visited, callback, value, arg);
diff --git a/src/stack.cc b/src/stack.cc
index c13aaf4..2567c50 100644
--- a/src/stack.cc
+++ b/src/stack.cc
@@ -80,7 +80,7 @@
 }
 
 
-uint32_t StackVisitor::GetVReg(Method* m, int vreg) const {
+uint32_t StackVisitor::GetVReg(AbstractMethod* m, int vreg) const {
   if (cur_quick_frame_ != NULL) {
     DCHECK(context_ != NULL); // You can't reliably read registers without a context.
     DCHECK(m == GetMethod());
@@ -115,7 +115,7 @@
   }
 }
 
-void StackVisitor::SetVReg(Method* m, int vreg, uint32_t new_value) {
+void StackVisitor::SetVReg(AbstractMethod* m, int vreg, uint32_t new_value) {
   if (cur_quick_frame_ != NULL) {
     DCHECK(context_ != NULL); // You can't reliably write registers without a context.
     DCHECK(m == GetMethod());
@@ -144,14 +144,14 @@
 }
 
 uintptr_t StackVisitor::GetReturnPc() const {
-  Method** sp = GetCurrentQuickFrame();
+  AbstractMethod** sp = GetCurrentQuickFrame();
   CHECK(sp != NULL);
   byte* pc_addr = reinterpret_cast<byte*>(sp) + GetMethod()->GetReturnPcOffsetInBytes();
   return *reinterpret_cast<uintptr_t*>(pc_addr);
 }
 
 void StackVisitor::SetReturnPc(uintptr_t new_ret_pc) {
-  Method** sp = GetCurrentQuickFrame();
+  AbstractMethod** sp = GetCurrentQuickFrame();
   CHECK(sp != NULL);
   byte* pc_addr = reinterpret_cast<byte*>(sp) + GetMethod()->GetReturnPcOffsetInBytes();
   *reinterpret_cast<uintptr_t*>(pc_addr) = new_ret_pc;
@@ -178,9 +178,9 @@
 
 void StackVisitor::SanityCheckFrame() const {
 #ifndef NDEBUG
-  Method* method = GetMethod();
-  CHECK(method->GetClass() == Method::GetMethodClass() ||
-        method->GetClass() == Method::GetConstructorClass());
+  AbstractMethod* method = GetMethod();
+  CHECK(method->GetClass() == AbstractMethod::GetMethodClass() ||
+        method->GetClass() == AbstractMethod::GetConstructorClass());
   if (cur_quick_frame_ != NULL) {
     method->AssertPcIsWithinCode(cur_quick_frame_pc_);
     // Frame sanity.
@@ -204,7 +204,7 @@
     if (cur_quick_frame_ != NULL) {  // Handle quick stack frames.
       // Can't be both a shadow and a quick fragment.
       DCHECK(current_fragment->GetTopShadowFrame() == NULL);
-      Method* method = *cur_quick_frame_;
+      AbstractMethod* method = *cur_quick_frame_;
       do {
         SanityCheckFrame();
         bool should_continue = VisitFrame();
@@ -234,7 +234,7 @@
         }
         cur_quick_frame_pc_ = return_pc;
         byte* next_frame = reinterpret_cast<byte*>(cur_quick_frame_) + frame_size;
-        cur_quick_frame_ = reinterpret_cast<Method**>(next_frame);
+        cur_quick_frame_ = reinterpret_cast<AbstractMethod**>(next_frame);
         cur_depth_++;
         method = *cur_quick_frame_;
       } while (method != NULL);
diff --git a/src/stack.h b/src/stack.h
index 21b05c4..4686c6b 100644
--- a/src/stack.h
+++ b/src/stack.h
@@ -28,7 +28,7 @@
 
 namespace art {
 
-class Method;
+class AbstractMethod;
 class Object;
 class ShadowFrame;
 class StackIndirectReferenceTable;
@@ -75,12 +75,12 @@
     references_[i] = object;
   }
 
-  Method* GetMethod() const {
+  AbstractMethod* GetMethod() const {
     DCHECK_NE(method_, static_cast<void*>(NULL));
     return method_;
   }
 
-  void SetMethod(Method* method) {
+  void SetMethod(AbstractMethod* method) {
     DCHECK_NE(method, static_cast<void*>(NULL));
     method_ = method;
   }
@@ -132,7 +132,7 @@
 
   uint32_t number_of_references_;
   ShadowFrame* link_;
-  Method* method_;
+  AbstractMethod* method_;
   uint32_t dex_pc_;
   Object* references_[];
 
@@ -154,11 +154,11 @@
     return link_;
   }
 
-  Method** GetTopQuickFrame() const {
+  AbstractMethod** GetTopQuickFrame() const {
     return top_quick_frame_;
   }
 
-  void SetTopQuickFrame(Method** top) {
+  void SetTopQuickFrame(AbstractMethod** top) {
     top_quick_frame_ = top;
   }
 
@@ -207,7 +207,7 @@
  private:
   ManagedStack* link_;
   ShadowFrame* top_shadow_frame_;
-  Method** top_quick_frame_;
+  AbstractMethod** top_quick_frame_;
   uintptr_t top_quick_frame_pc_;
 };
 
@@ -229,7 +229,7 @@
   void WalkStack(bool include_transitions = false)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  Method* GetMethod() const {
+  AbstractMethod* GetMethod() const {
     if (cur_shadow_frame_ != NULL) {
       return cur_shadow_frame_->GetMethod();
     } else if (cur_quick_frame_ != NULL) {
@@ -249,7 +249,7 @@
 
   uintptr_t LoadCalleeSave(int num, size_t frame_size) const {
     // Callee saves are held at the top of the frame
-    Method* method = GetMethod();
+    AbstractMethod* method = GetMethod();
     DCHECK(method != NULL);
     byte* save_addr =
         reinterpret_cast<byte*>(cur_quick_frame_) + frame_size - ((num + 1) * kPointerSize);
@@ -276,14 +276,14 @@
     return num_frames_;
   }
 
-  uint32_t GetVReg(Method* m, int vreg) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  uint32_t GetVReg(AbstractMethod* m, int vreg) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void SetVReg(Method* m, int vreg, uint32_t new_value)
+  void SetVReg(AbstractMethod* m, int vreg, uint32_t new_value)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   uintptr_t GetGPR(uint32_t reg) const;
 
-  uint32_t GetVReg(Method** cur_quick_frame, const DexFile::CodeItem* code_item,
+  uint32_t GetVReg(AbstractMethod** cur_quick_frame, const DexFile::CodeItem* code_item,
                    uint32_t core_spills, uint32_t fp_spills, size_t frame_size, int vreg) const {
     int offset = GetVRegOffset(code_item, core_spills, fp_spills, frame_size, vreg);
     DCHECK_EQ(cur_quick_frame, GetCurrentQuickFrame());
@@ -356,7 +356,7 @@
     return cur_quick_frame_pc_;
   }
 
-  Method** GetCurrentQuickFrame() const {
+  AbstractMethod** GetCurrentQuickFrame() const {
     return cur_quick_frame_;
   }
 
@@ -365,7 +365,7 @@
   }
 
   StackIndirectReferenceTable* GetCurrentSirt() const {
-    Method** sp = GetCurrentQuickFrame();
+    AbstractMethod** sp = GetCurrentQuickFrame();
     ++sp; // Skip Method*; SIRT comes next;
     return reinterpret_cast<StackIndirectReferenceTable*>(sp);
   }
@@ -382,7 +382,7 @@
   const ManagedStack* const stack_start_;
   const std::vector<TraceStackFrame>* const trace_stack_;
   ShadowFrame* cur_shadow_frame_;
-  Method** cur_quick_frame_;
+  AbstractMethod** cur_quick_frame_;
   uintptr_t cur_quick_frame_pc_;
   // Lazily computed, number of frames in the stack.
   size_t num_frames_;
diff --git a/src/thread.cc b/src/thread.cc
index eaa6683..9db25f4 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -115,7 +115,7 @@
     CHECK(self->peer_ != NULL);
     Object* receiver = self->peer_;
     jmethodID mid = WellKnownClasses::java_lang_Thread_run;
-    Method* m = receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(soa.DecodeMethod(mid));
+    AbstractMethod* m = receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(soa.DecodeMethod(mid));
     m->Invoke(self, receiver, NULL, NULL);
   }
 
@@ -708,7 +708,7 @@
   }
 
   bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    Method* m = GetMethod();
+    AbstractMethod* m = GetMethod();
     if (m->IsRuntimeMethod()) {
       return true;
     }
@@ -757,7 +757,7 @@
   const Thread* thread;
   bool can_allocate;
   MethodHelper mh;
-  Method* last_method;
+  AbstractMethod* last_method;
   int last_line_number;
   int repetition_count;
   int frame_count;
@@ -962,7 +962,7 @@
 
   // Call the handler.
   jmethodID mid = WellKnownClasses::java_lang_Thread$UncaughtExceptionHandler_uncaughtException;
-  Method* m = handler->GetClass()->FindVirtualMethodForVirtualOrInterface(soa.DecodeMethod(mid));
+  AbstractMethod* m = handler->GetClass()->FindVirtualMethodForVirtualOrInterface(soa.DecodeMethod(mid));
   JValue args[2];
   args[0].SetL(peer_);
   args[1].SetL(exception);
@@ -982,7 +982,7 @@
   Object* group = GetThreadGroup(soa);
   if (group != NULL) {
     jmethodID mid = WellKnownClasses::java_lang_ThreadGroup_removeThread;
-    Method* m = group->GetClass()->FindVirtualMethodForVirtualOrInterface(soa.DecodeMethod(mid));
+    AbstractMethod* m = group->GetClass()->FindVirtualMethodForVirtualOrInterface(soa.DecodeMethod(mid));
     JValue args[1];
     args[0].SetL(peer_);
     m->Invoke(this, group, args, NULL);
@@ -1091,7 +1091,7 @@
     // We want to skip frames up to and including the exception's constructor.
     // Note we also skip the frame if it doesn't have a method (namely the callee
     // save frame)
-    Method* m = GetMethod();
+    AbstractMethod* m = GetMethod();
     if (skipping_ && !m->IsRuntimeMethod() &&
         !Throwable::GetJavaLangThrowable()->IsAssignableFrom(m->GetDeclaringClass())) {
       skipping_ = false;
@@ -1166,7 +1166,7 @@
       skip_depth_--;
       return true;
     }
-    Method* m = GetMethod();
+    AbstractMethod* m = GetMethod();
     if (m->IsRuntimeMethod()) {
       return true;  // Ignore runtime frames (in particular callee save).
     }
@@ -1255,7 +1255,7 @@
   MethodHelper mh;
   for (int32_t i = 0; i < depth; ++i) {
     // Prepare parameters for StackTraceElement(String cls, String method, String file, int line)
-    Method* method = down_cast<Method*>(method_trace->Get(i));
+    AbstractMethod* method = down_cast<AbstractMethod*>(method_trace->Get(i));
     mh.ChangeMethod(method);
     uint32_t dex_pc = pc_trace->Get(i);
     int32_t line_number = mh.GetLineNumFromDexPC(dex_pc);
@@ -1535,7 +1535,7 @@
 
   bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    Method* method = GetMethod();
+    AbstractMethod* method = GetMethod();
     if (method == NULL) {
       // This is the upcall, we remember the frame and last pc so that we may long jump to them.
       handler_quick_frame_pc_ = GetCurrentQuickFramePc();
@@ -1577,7 +1577,7 @@
   }
 
   void DoLongJump() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    Method* catch_method = *handler_quick_frame_;
+    AbstractMethod* catch_method = *handler_quick_frame_;
     Dbg::PostException(self_, throw_frame_id_, throw_method_, throw_dex_pc_,
                        catch_method, handler_dex_pc_, exception_);
     if (kDebugExceptionDelivery) {
@@ -1607,11 +1607,11 @@
   Throwable* exception_;
   // The type of the exception catch block to find.
   Class* to_find_;
-  Method* throw_method_;
+  AbstractMethod* throw_method_;
   JDWP::FrameId throw_frame_id_;
   uint32_t throw_dex_pc_;
   // Quick frame with found handler or last frame if no handler found.
-  Method** handler_quick_frame_;
+  AbstractMethod** handler_quick_frame_;
   // PC to branch to for the handler.
   uintptr_t handler_quick_frame_pc_;
   // Associated dex PC.
@@ -1652,7 +1652,7 @@
   return result;
 }
 
-Method* Thread::GetCurrentMethod(uint32_t* dex_pc, size_t* frame_id) const {
+AbstractMethod* Thread::GetCurrentMethod(uint32_t* dex_pc, size_t* frame_id) const {
   struct CurrentMethodVisitor : public StackVisitor {
     CurrentMethodVisitor(const ManagedStack* stack,
                          const std::vector<TraceStackFrame>* trace_stack)
@@ -1660,7 +1660,7 @@
         : StackVisitor(stack, trace_stack, NULL), method_(NULL), dex_pc_(0), frame_id_(0) {}
 
     virtual bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-      Method* m = GetMethod();
+      AbstractMethod* m = GetMethod();
       if (m->IsRuntimeMethod()) {
         // Continue if this is a runtime method.
         return true;
@@ -1670,7 +1670,7 @@
       frame_id_ = GetFrameId();
       return false;
     }
-    Method* method_;
+    AbstractMethod* method_;
     uint32_t dex_pc_;
     size_t frame_id_;
   };
@@ -1709,7 +1709,7 @@
     if (shadow_frame != NULL) {
       shadow_frame->VisitRoots(root_visitor_, arg_);
     } else {
-      Method* m = GetMethod();
+      AbstractMethod* m = GetMethod();
       // Process register map (which native and runtime methods don't have)
       if (!m->IsNative() && !m->IsRuntimeMethod() && !m->IsProxyMethod()) {
         const uint8_t* native_gc_map = m->GetNativeGcMap();
@@ -1728,7 +1728,7 @@
           uint32_t fp_spills = m->GetFpSpillMask();
           size_t frame_size = m->GetFrameSizeInBytes();
           // For all dex registers in the bitmap
-          Method** cur_quick_frame = GetCurrentQuickFrame();
+          AbstractMethod** cur_quick_frame = GetCurrentQuickFrame();
           DCHECK(cur_quick_frame != NULL);
           for (size_t reg = 0; reg < num_regs; ++reg) {
             // Does this register hold a reference?
diff --git a/src/thread.h b/src/thread.h
index 6fbf1d2..ad861e0 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -50,7 +50,7 @@
 class ClassLoader;
 class Context;
 struct DebugInvokeReq;
-class Method;
+class AbstractMethod;
 class Monitor;
 class Object;
 class Runtime;
@@ -347,11 +347,11 @@
     long_jump_context_ = context;
   }
 
-  Method* GetCurrentMethod(uint32_t* dex_pc = NULL, size_t* frame_id = NULL) const
+  AbstractMethod* GetCurrentMethod(uint32_t* dex_pc = NULL, size_t* frame_id = NULL) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void SetTopOfStack(void* stack, uintptr_t pc) {
-    Method** top_method = reinterpret_cast<Method**>(stack);
+    AbstractMethod** top_method = reinterpret_cast<AbstractMethod**>(stack);
     managed_stack_.SetTopQuickFrame(top_method);
     managed_stack_.SetTopQuickFramePc(pc);
   }
@@ -383,7 +383,7 @@
 
   //QuickFrameIterator FindExceptionHandler(void* throw_pc, void** handler_pc);
 
-  void* FindExceptionHandlerInMethod(const Method* method,
+  void* FindExceptionHandlerInMethod(const AbstractMethod* method,
                                      void* throw_pc,
                                      const DexFile& dex_file,
                                      ClassLinker* class_linker);
diff --git a/src/trace.cc b/src/trace.cc
index e4bc836..d1f3f50 100644
--- a/src/trace.cc
+++ b/src/trace.cc
@@ -162,14 +162,14 @@
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   Trace* tracer = Runtime::Current()->GetTracer();
   for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
-    Method* method = klass->GetDirectMethod(i);
+    AbstractMethod* method = klass->GetDirectMethod(i);
     if (tracer->GetSavedCodeFromMap(method) == NULL) {
       tracer->SaveAndUpdateCode(method);
     }
   }
 
   for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
-    Method* method = klass->GetVirtualMethod(i);
+    AbstractMethod* method = klass->GetVirtualMethod(i);
     if (tracer->GetSavedCodeFromMap(method) == NULL) {
       tracer->SaveAndUpdateCode(method);
     }
@@ -181,14 +181,14 @@
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   Trace* tracer = Runtime::Current()->GetTracer();
   for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
-    Method* method = klass->GetDirectMethod(i);
+    AbstractMethod* method = klass->GetDirectMethod(i);
     if (tracer->GetSavedCodeFromMap(method) != NULL) {
       tracer->ResetSavedCode(method);
     }
   }
 
   for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
-    Method* method = klass->GetVirtualMethod(i);
+    AbstractMethod* method = klass->GetVirtualMethod(i);
     if (tracer->GetSavedCodeFromMap(method) != NULL) {
       tracer->ResetSavedCode(method);
     }
@@ -221,16 +221,16 @@
   visitor.WalkStack();
 }
 
-void Trace::AddSavedCodeToMap(const Method* method, const void* code) {
+void Trace::AddSavedCodeToMap(const AbstractMethod* method, const void* code) {
   saved_code_map_.Put(method, code);
 }
 
-void Trace::RemoveSavedCodeFromMap(const Method* method) {
+void Trace::RemoveSavedCodeFromMap(const AbstractMethod* method) {
   saved_code_map_.erase(method);
 }
 
-const void* Trace::GetSavedCodeFromMap(const Method* method) {
-  typedef SafeMap<const Method*, const void*>::const_iterator It; // TODO: C++0x auto
+const void* Trace::GetSavedCodeFromMap(const AbstractMethod* method) {
+  typedef SafeMap<const AbstractMethod*, const void*>::const_iterator It; // TODO: C++0x auto
   It it = saved_code_map_.find(method);
   if (it == saved_code_map_.end()) {
     return NULL;
@@ -239,7 +239,7 @@
   }
 }
 
-void Trace::SaveAndUpdateCode(Method* method) {
+void Trace::SaveAndUpdateCode(AbstractMethod* method) {
 #if defined(ART_USE_LLVM_COMPILER)
   UNIMPLEMENTED(FATAL);
 #else
@@ -250,7 +250,7 @@
 #endif
 }
 
-void Trace::ResetSavedCode(Method* method) {
+void Trace::ResetSavedCode(AbstractMethod* method) {
   CHECK(GetSavedCodeFromMap(method) != NULL);
   method->SetCode(GetSavedCodeFromMap(method));
   RemoveSavedCodeFromMap(method);
@@ -419,7 +419,7 @@
   }
 }
 
-void Trace::LogMethodTraceEvent(Thread* self, const Method* method, Trace::TraceEvent event) {
+void Trace::LogMethodTraceEvent(Thread* self, const AbstractMethod* method, Trace::TraceEvent event) {
   if (thread_clock_base_map_.find(self) == thread_clock_base_map_.end()) {
     uint64_t time = ThreadCpuMicroTime();
     thread_clock_base_map_.Put(self, time);
@@ -464,16 +464,16 @@
 
   while (ptr < end) {
     uint32_t method_value = ptr[2] | (ptr[3] << 8) | (ptr[4] << 16) | (ptr[5] << 24);
-    Method* method = reinterpret_cast<Method*>(TraceMethodId(method_value));
+    AbstractMethod* method = reinterpret_cast<AbstractMethod*>(TraceMethodId(method_value));
     visited_methods_.insert(method);
     ptr += record_size_;
   }
 }
 
 void Trace::DumpMethodList(std::ostream& os) {
-  typedef std::set<const Method*>::const_iterator It; // TODO: C++0x auto
+  typedef std::set<const AbstractMethod*>::const_iterator It; // TODO: C++0x auto
   for (It it = visited_methods_.begin(); it != visited_methods_.end(); ++it) {
-    const Method* method = *it;
+    const AbstractMethod* method = *it;
     MethodHelper mh(method);
     os << StringPrintf("%p\t%s\t%s\t%s\t%s\n", method,
         PrettyDescriptor(mh.GetDeclaringClassDescriptor()).c_str(), mh.GetName(),
@@ -508,7 +508,7 @@
 uint32_t TraceMethodUnwindFromCode(Thread* self) {
   Trace* tracer = Runtime::Current()->GetTracer();
   TraceStackFrame trace_frame = self->PopTraceStackFrame();
-  Method* method = trace_frame.method_;
+  AbstractMethod* method = trace_frame.method_;
   uint32_t lr = trace_frame.return_pc_;
 
   tracer->LogMethodTraceEvent(self, method, Trace::kMethodTraceUnwind);
diff --git a/src/trace.h b/src/trace.h
index 9c64347..43b0ff7 100644
--- a/src/trace.h
+++ b/src/trace.h
@@ -29,17 +29,17 @@
 
 namespace art {
 
-class Method;
+class AbstractMethod;
 class Thread;
 
 uint32_t TraceMethodUnwindFromCode(Thread* self);
 
 struct TraceStackFrame {
-  TraceStackFrame(Method* method, uintptr_t return_pc)
+  TraceStackFrame(AbstractMethod* method, uintptr_t return_pc)
       : method_(method), return_pc_(return_pc) {
   }
 
-  Method* method_;
+  AbstractMethod* method_;
   uintptr_t return_pc_;
 };
 
@@ -70,14 +70,14 @@
   bool UseWallClock();
   bool UseThreadCpuClock();
 
-  void LogMethodTraceEvent(Thread* self, const Method* method, TraceEvent event);
+  void LogMethodTraceEvent(Thread* self, const AbstractMethod* method, TraceEvent event);
 
-  void AddSavedCodeToMap(const Method* method, const void* code);
-  void RemoveSavedCodeFromMap(const Method* method);
-  const void* GetSavedCodeFromMap(const Method* method);
+  void AddSavedCodeToMap(const AbstractMethod* method, const void* code);
+  void RemoveSavedCodeFromMap(const AbstractMethod* method);
+  const void* GetSavedCodeFromMap(const AbstractMethod* method);
 
-  void SaveAndUpdateCode(Method* method);
-  void ResetSavedCode(Method* method);
+  void SaveAndUpdateCode(AbstractMethod* method);
+  void ResetSavedCode(AbstractMethod* method);
 
  private:
   explicit Trace(File* trace_file, int buffer_size, int flags);
@@ -97,10 +97,10 @@
   void DumpThreadList(std::ostream& os) LOCKS_EXCLUDED(Locks::thread_list_lock_);
 
   // Maps a method to its original code pointer.
-  SafeMap<const Method*, const void*> saved_code_map_;
+  SafeMap<const AbstractMethod*, const void*> saved_code_map_;
 
   // Set of methods visited by the profiler.
-  std::set<const Method*> visited_methods_;
+  std::set<const AbstractMethod*> visited_methods_;
 
   // Maps a thread to its clock base.
   SafeMap<Thread*, uint64_t> thread_clock_base_map_;
diff --git a/src/utils.cc b/src/utils.cc
index bff1f0c..534b28e 100644
--- a/src/utils.cc
+++ b/src/utils.cc
@@ -317,7 +317,7 @@
   return PrettyDescriptor(return_type);
 }
 
-std::string PrettyMethod(const Method* m, bool with_signature) {
+std::string PrettyMethod(const AbstractMethod* m, bool with_signature) {
   if (m == NULL) {
     return "null";
   }
@@ -573,7 +573,7 @@
   return descriptor;
 }
 
-std::string JniShortName(const Method* m) {
+std::string JniShortName(const AbstractMethod* m) {
   MethodHelper mh(m);
   std::string class_name(mh.GetDeclaringClassDescriptor());
   // Remove the leading 'L' and trailing ';'...
@@ -592,7 +592,7 @@
   return short_name;
 }
 
-std::string JniLongName(const Method* m) {
+std::string JniLongName(const AbstractMethod* m) {
   std::string long_name;
   long_name += JniShortName(m);
   long_name += "__";
diff --git a/src/utils.h b/src/utils.h
index b59f114..7daf61c 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -32,7 +32,7 @@
 class Class;
 class DexFile;
 class Field;
-class Method;
+class AbstractMethod;
 class Object;
 class String;
 
@@ -185,7 +185,7 @@
 
 // Returns a human-readable signature for 'm'. Something like "a.b.C.m" or
 // "a.b.C.m(II)V" (depending on the value of 'with_signature').
-std::string PrettyMethod(const Method* m, bool with_signature = true)
+std::string PrettyMethod(const AbstractMethod* m, bool with_signature = true)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 std::string PrettyMethod(uint32_t method_idx, const DexFile& dex_file, bool with_signature = true);
 
@@ -249,10 +249,10 @@
 bool IsValidMemberName(const char* s);
 
 // Returns the JNI native function name for the non-overloaded method 'm'.
-std::string JniShortName(const Method* m)
+std::string JniShortName(const AbstractMethod* m)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 // Returns the JNI native function name for the overloaded method 'm'.
-std::string JniLongName(const Method* m)
+std::string JniLongName(const AbstractMethod* m)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 bool ReadFileToString(const std::string& file_name, std::string* result);
diff --git a/src/utils_test.cc b/src/utils_test.cc
index e6ff118..0b27fc5 100644
--- a/src/utils_test.cc
+++ b/src/utils_test.cc
@@ -194,7 +194,7 @@
   ScopedObjectAccess soa(Thread::Current());
   Class* c = class_linker_->FindSystemClass("Ljava/lang/String;");
   ASSERT_TRUE(c != NULL);
-  Method* m;
+  AbstractMethod* m;
 
   m = c->FindVirtualMethod("charAt", "(I)C");
   ASSERT_TRUE(m != NULL);
diff --git a/src/verifier/method_verifier.cc b/src/verifier/method_verifier.cc
index ac9a0c9..f4884ad 100644
--- a/src/verifier/method_verifier.cc
+++ b/src/verifier/method_verifier.cc
@@ -215,7 +215,7 @@
   while (it.HasNextDirectMethod()) {
     uint32_t method_idx = it.GetMemberIndex();
     InvokeType type = it.GetMethodInvokeType(class_def);
-    Method* method = linker->ResolveMethod(*dex_file, method_idx, dex_cache, class_loader, NULL, type);
+    AbstractMethod* method = linker->ResolveMethod(*dex_file, method_idx, dex_cache, class_loader, NULL, type);
     if (method == NULL) {
       DCHECK(Thread::Current()->IsExceptionPending());
       // We couldn't resolve the method, but continue regardless.
@@ -241,7 +241,7 @@
   while (it.HasNextVirtualMethod()) {
     uint32_t method_idx = it.GetMemberIndex();
     InvokeType type = it.GetMethodInvokeType(class_def);
-    Method* method = linker->ResolveMethod(*dex_file, method_idx, dex_cache, class_loader, NULL, type);
+    AbstractMethod* method = linker->ResolveMethod(*dex_file, method_idx, dex_cache, class_loader, NULL, type);
     if (method == NULL) {
       DCHECK(Thread::Current()->IsExceptionPending());
       // We couldn't resolve the method, but continue regardless.
@@ -273,7 +273,7 @@
 
 MethodVerifier::FailureKind MethodVerifier::VerifyMethod(uint32_t method_idx, const DexFile* dex_file,
     DexCache* dex_cache, ClassLoader* class_loader, uint32_t class_def_idx,
-    const DexFile::CodeItem* code_item, Method* method, uint32_t method_access_flags) {
+    const DexFile::CodeItem* code_item, AbstractMethod* method, uint32_t method_access_flags) {
   MethodVerifier::FailureKind result = kNoFailure;
   uint64_t start_ns = NanoTime();
 
@@ -308,7 +308,7 @@
   return result;
 }
 
-void MethodVerifier::VerifyMethodAndDump(Method* method) {
+void MethodVerifier::VerifyMethodAndDump(AbstractMethod* method) {
   CHECK(method != NULL);
   MethodHelper mh(method);
   MethodVerifier verifier(&mh.GetDexFile(), mh.GetDexCache(), mh.GetClassLoader(),
@@ -321,7 +321,7 @@
 
 MethodVerifier::MethodVerifier(const DexFile* dex_file, DexCache* dex_cache,
     ClassLoader* class_loader, uint32_t class_def_idx, const DexFile::CodeItem* code_item,
-    uint32_t method_idx, Method* method, uint32_t method_access_flags)
+    uint32_t method_idx, AbstractMethod* method, uint32_t method_access_flags)
     : work_insn_idx_(-1),
       method_idx_(method_idx),
       foo_method_(method),
@@ -339,7 +339,7 @@
       monitor_enter_count_(0) {
 }
 
-void MethodVerifier::FindLocksAtDexPc(Method* m, uint32_t dex_pc, std::vector<uint32_t>& monitor_enter_dex_pcs) {
+void MethodVerifier::FindLocksAtDexPc(AbstractMethod* m, uint32_t dex_pc, std::vector<uint32_t>& monitor_enter_dex_pcs) {
   MethodHelper mh(m);
   MethodVerifier verifier(&mh.GetDexFile(), mh.GetDexCache(), mh.GetClassLoader(),
                           mh.GetClassDefIndex(), mh.GetCodeItem(), m->GetDexMethodIndex(),
@@ -1890,7 +1890,7 @@
                        dec_insn.opcode == Instruction::INVOKE_SUPER_RANGE);
       bool is_super =  (dec_insn.opcode == Instruction::INVOKE_SUPER ||
                         dec_insn.opcode == Instruction::INVOKE_SUPER_RANGE);
-      Method* called_method = VerifyInvocationArgs(dec_insn, METHOD_VIRTUAL, is_range, is_super);
+      AbstractMethod* called_method = VerifyInvocationArgs(dec_insn, METHOD_VIRTUAL, is_range, is_super);
       const char* descriptor;
       if (called_method == NULL) {
         uint32_t method_idx = dec_insn.vB;
@@ -1908,7 +1908,7 @@
     case Instruction::INVOKE_DIRECT:
     case Instruction::INVOKE_DIRECT_RANGE: {
       bool is_range = (dec_insn.opcode == Instruction::INVOKE_DIRECT_RANGE);
-      Method* called_method = VerifyInvocationArgs(dec_insn, METHOD_DIRECT, is_range, false);
+      AbstractMethod* called_method = VerifyInvocationArgs(dec_insn, METHOD_DIRECT, is_range, false);
       const char* return_type_descriptor;
       bool is_constructor;
       if (called_method == NULL) {
@@ -1969,7 +1969,7 @@
     case Instruction::INVOKE_STATIC:
     case Instruction::INVOKE_STATIC_RANGE: {
         bool is_range = (dec_insn.opcode == Instruction::INVOKE_STATIC_RANGE);
-        Method* called_method = VerifyInvocationArgs(dec_insn, METHOD_STATIC, is_range, false);
+        AbstractMethod* called_method = VerifyInvocationArgs(dec_insn, METHOD_STATIC, is_range, false);
         const char* descriptor;
         if (called_method == NULL) {
           uint32_t method_idx = dec_insn.vB;
@@ -1987,7 +1987,7 @@
     case Instruction::INVOKE_INTERFACE:
     case Instruction::INVOKE_INTERFACE_RANGE: {
       bool is_range =  (dec_insn.opcode == Instruction::INVOKE_INTERFACE_RANGE);
-      Method* abs_method = VerifyInvocationArgs(dec_insn, METHOD_INTERFACE, is_range, false);
+      AbstractMethod* abs_method = VerifyInvocationArgs(dec_insn, METHOD_INTERFACE, is_range, false);
       if (abs_method != NULL) {
         Class* called_interface = abs_method->GetDeclaringClass();
         if (!called_interface->IsInterface() && !called_interface->IsObjectClass()) {
@@ -2511,7 +2511,7 @@
   return *common_super;
 }
 
-Method* MethodVerifier::ResolveMethodAndCheckAccess(uint32_t dex_method_idx, MethodType method_type) {
+AbstractMethod* MethodVerifier::ResolveMethodAndCheckAccess(uint32_t dex_method_idx, MethodType method_type) {
   const DexFile::MethodId& method_id = dex_file_->GetMethodId(dex_method_idx);
   const RegType& klass_type = ResolveClassAndCheckAccess(method_id.class_idx_);
   if (klass_type.IsConflict()) {
@@ -2525,7 +2525,7 @@
   }
   Class* klass = klass_type.GetClass();
   const RegType& referrer = GetDeclaringClass();
-  Method* res_method = dex_cache_->GetResolvedMethod(dex_method_idx);
+  AbstractMethod* res_method = dex_cache_->GetResolvedMethod(dex_method_idx);
   if (res_method == NULL) {
     const char* name = dex_file_->GetMethodName(method_id);
     std::string signature(dex_file_->CreateMethodSignature(method_id.proto_idx_, NULL));
@@ -2602,11 +2602,11 @@
   return res_method;
 }
 
-Method* MethodVerifier::VerifyInvocationArgs(const DecodedInstruction& dec_insn,
+AbstractMethod* MethodVerifier::VerifyInvocationArgs(const DecodedInstruction& dec_insn,
                                              MethodType method_type, bool is_range, bool is_super) {
   // Resolve the method. This could be an abstract or concrete method depending on what sort of call
   // we're making.
-  Method* res_method = ResolveMethodAndCheckAccess(dec_insn.vB, method_type);
+  AbstractMethod* res_method = ResolveMethodAndCheckAccess(dec_insn.vB, method_type);
   if (res_method == NULL) {  // error or class is unresolved
     return NULL;
   }
diff --git a/src/verifier/method_verifier.h b/src/verifier/method_verifier.h
index c1c2562..8951b13 100644
--- a/src/verifier/method_verifier.h
+++ b/src/verifier/method_verifier.h
@@ -193,7 +193,7 @@
 
   // Fills 'monitor_enter_dex_pcs' with the dex pcs of the monitor-enter instructions corresponding
   // to the locks held at 'dex_pc' in 'm'.
-  static void FindLocksAtDexPc(Method* m, uint32_t dex_pc,
+  static void FindLocksAtDexPc(AbstractMethod* m, uint32_t dex_pc,
                                std::vector<uint32_t>& monitor_enter_dex_pcs)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -211,7 +211,7 @@
  private:
   explicit MethodVerifier(const DexFile* dex_file, DexCache* dex_cache,
       ClassLoader* class_loader, uint32_t class_def_idx, const DexFile::CodeItem* code_item,
-      uint32_t method_idx, Method* method, uint32_t access_flags)
+      uint32_t method_idx, AbstractMethod* method, uint32_t access_flags)
           SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Adds the given string to the beginning of the last failure message.
@@ -233,9 +233,9 @@
    */
   static FailureKind VerifyMethod(uint32_t method_idx, const DexFile* dex_file, DexCache* dex_cache,
       ClassLoader* class_loader, uint32_t class_def_idx, const DexFile::CodeItem* code_item,
-      Method* method, uint32_t method_access_flags)
+      AbstractMethod* method, uint32_t method_access_flags)
           SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  static void VerifyMethodAndDump(Method* method)
+  static void VerifyMethodAndDump(AbstractMethod* method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Run verification on the method. Returns true if verification completes and false if the input
@@ -493,7 +493,7 @@
    * the referrer can access the resolved method.
    * Does not throw exceptions.
    */
-  Method* ResolveMethodAndCheckAccess(uint32_t method_idx, MethodType method_type)
+  AbstractMethod* ResolveMethodAndCheckAccess(uint32_t method_idx, MethodType method_type)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   /*
@@ -518,7 +518,7 @@
    * Returns the resolved method on success, NULL on failure (with *failure
    * set appropriately).
    */
-  Method* VerifyInvocationArgs(const DecodedInstruction& dec_insn,
+  AbstractMethod* VerifyInvocationArgs(const DecodedInstruction& dec_insn,
                                MethodType method_type, bool is_range, bool is_super)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -618,7 +618,7 @@
 
   uint32_t method_idx_;  // The method we're working on.
   // Its object representation if known.
-  Method* foo_method_ GUARDED_BY(Locks::mutator_lock_);
+  AbstractMethod* foo_method_ GUARDED_BY(Locks::mutator_lock_);
   uint32_t method_access_flags_;  // Method's access flags.
   const DexFile* dex_file_;  // The dex file containing the method.
   // The dex_cache for the declaring class of the method.
diff --git a/src/well_known_classes.cc b/src/well_known_classes.cc
index cae7369..1413f0b 100644
--- a/src/well_known_classes.cc
+++ b/src/well_known_classes.cc
@@ -31,7 +31,7 @@
 jclass WellKnownClasses::java_lang_Daemons;
 jclass WellKnownClasses::java_lang_Error;
 jclass WellKnownClasses::java_lang_reflect_InvocationHandler;
-jclass WellKnownClasses::java_lang_reflect_Method;
+jclass WellKnownClasses::java_lang_reflect_AbstractMethod;
 jclass WellKnownClasses::java_lang_reflect_Proxy;
 jclass WellKnownClasses::java_lang_RuntimeException;
 jclass WellKnownClasses::java_lang_Thread;
@@ -125,7 +125,7 @@
   java_lang_Daemons = CacheClass(env, "java/lang/Daemons");
   java_lang_Error = CacheClass(env, "java/lang/Error");
   java_lang_reflect_InvocationHandler = CacheClass(env, "java/lang/reflect/InvocationHandler");
-  java_lang_reflect_Method = CacheClass(env, "java/lang/reflect/Method");
+  java_lang_reflect_AbstractMethod = CacheClass(env, "java/lang/reflect/AbstractMethod");
   java_lang_reflect_Proxy = CacheClass(env, "java/lang/reflect/Proxy");
   java_lang_RuntimeException = CacheClass(env, "java/lang/RuntimeException");
   java_lang_Thread = CacheClass(env, "java/lang/Thread");
diff --git a/src/well_known_classes.h b/src/well_known_classes.h
index 65ee6b4..15a204f 100644
--- a/src/well_known_classes.h
+++ b/src/well_known_classes.h
@@ -42,7 +42,7 @@
   static jclass java_lang_Daemons;
   static jclass java_lang_Error;
   static jclass java_lang_reflect_InvocationHandler;
-  static jclass java_lang_reflect_Method;
+  static jclass java_lang_reflect_AbstractMethod;
   static jclass java_lang_reflect_Proxy;
   static jclass java_lang_RuntimeException;
   static jclass java_lang_Thread;