Improvements to Field.get/set.

Avoid unnecessary repeated computation in Field.get/set.
Refactor FromReflectedField and FromReflectedMethod into common helpers in
mirror::ArtField and mirror::ArtMethod, and make use of thereby avoiding
transitions through JNI.
Avoid JNI use from within FromReflectedField and FromReflectedMethod.
Tidy up Field.get/set wrt moving collector support.
Bug: 12189533

Change-Id: I643ab3474bade4abac3a3ae2b6e373b2bb0891c8
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index cef9954..08ea123 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -2314,26 +2314,26 @@
 }
 
 mirror::Class* ClassLinker::FindPrimitiveClass(char type) {
-  switch (Primitive::GetType(type)) {
-    case Primitive::kPrimByte:
+  switch (type) {
+    case 'B':
       return GetClassRoot(kPrimitiveByte);
-    case Primitive::kPrimChar:
+    case 'C':
       return GetClassRoot(kPrimitiveChar);
-    case Primitive::kPrimDouble:
+    case 'D':
       return GetClassRoot(kPrimitiveDouble);
-    case Primitive::kPrimFloat:
+    case 'F':
       return GetClassRoot(kPrimitiveFloat);
-    case Primitive::kPrimInt:
+    case 'I':
       return GetClassRoot(kPrimitiveInt);
-    case Primitive::kPrimLong:
+    case 'J':
       return GetClassRoot(kPrimitiveLong);
-    case Primitive::kPrimShort:
+    case 'S':
       return GetClassRoot(kPrimitiveShort);
-    case Primitive::kPrimBoolean:
+    case 'Z':
       return GetClassRoot(kPrimitiveBoolean);
-    case Primitive::kPrimVoid:
+    case 'V':
       return GetClassRoot(kPrimitiveVoid);
-    case Primitive::kPrimNot:
+    default:
       break;
   }
   std::string printable_type(PrintableChar(type));
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index 43db7ec..13aa77f 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -550,24 +550,16 @@
     return soa.AddLocalReference<jclass>(c);
   }
 
-  static jmethodID FromReflectedMethod(JNIEnv* env, jobject java_method) {
-    CHECK_NON_NULL_ARGUMENT(FromReflectedMethod, java_method);
+  static jmethodID FromReflectedMethod(JNIEnv* env, jobject jlr_method) {
+    CHECK_NON_NULL_ARGUMENT(FromReflectedMethod, jlr_method);
     ScopedObjectAccess soa(env);
-    jobject art_method = env->GetObjectField(
-        java_method, WellKnownClasses::java_lang_reflect_AbstractMethod_artMethod);
-    mirror::ArtMethod* method = soa.Decode<mirror::ArtMethod*>(art_method);
-    DCHECK(method != nullptr);
-    return soa.EncodeMethod(method);
+    return soa.EncodeMethod(mirror::ArtMethod::FromReflectedMethod(soa, jlr_method));
   }
 
-  static jfieldID FromReflectedField(JNIEnv* env, jobject java_field) {
-    CHECK_NON_NULL_ARGUMENT(FromReflectedField, java_field);
+  static jfieldID FromReflectedField(JNIEnv* env, jobject jlr_field) {
+    CHECK_NON_NULL_ARGUMENT(FromReflectedField, jlr_field);
     ScopedObjectAccess soa(env);
-    jobject art_field = env->GetObjectField(java_field,
-                                            WellKnownClasses::java_lang_reflect_Field_artField);
-    mirror::ArtField* field = soa.Decode<mirror::ArtField*>(art_field);
-    DCHECK(field != nullptr);
-    return soa.EncodeField(field);
+    return soa.EncodeField(mirror::ArtField::FromReflectedField(soa, jlr_field));
   }
 
   static jobject ToReflectedMethod(JNIEnv* env, jclass, jmethodID mid, jboolean) {
diff --git a/runtime/mirror/art_field.cc b/runtime/mirror/art_field.cc
index 7740213..f91cab1 100644
--- a/runtime/mirror/art_field.cc
+++ b/runtime/mirror/art_field.cc
@@ -21,7 +21,9 @@
 #include "object-inl.h"
 #include "object_utils.h"
 #include "runtime.h"
+#include "scoped_thread_state_change.h"
 #include "utils.h"
+#include "well_known_classes.h"
 
 namespace art {
 namespace mirror {
@@ -29,6 +31,13 @@
 // TODO: get global references for these
 Class* ArtField::java_lang_reflect_ArtField_ = NULL;
 
+ArtField* ArtField::FromReflectedField(const ScopedObjectAccess& soa, jobject jlr_field) {
+  mirror::ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_reflect_Field_artField);
+  mirror::ArtField* field = f->GetObject(soa.Decode<mirror::Object*>(jlr_field))->AsArtField();
+  DCHECK(field != nullptr);
+  return field;
+}
+
 void ArtField::SetClass(Class* java_lang_reflect_ArtField) {
   CHECK(java_lang_reflect_ArtField_ == NULL);
   CHECK(java_lang_reflect_ArtField != NULL);
diff --git a/runtime/mirror/art_field.h b/runtime/mirror/art_field.h
index 46287c3e..0daa838 100644
--- a/runtime/mirror/art_field.h
+++ b/runtime/mirror/art_field.h
@@ -25,12 +25,16 @@
 namespace art {
 
 struct ArtFieldOffsets;
+class ScopedObjectAccess;
 
 namespace mirror {
 
 // C++ mirror of java.lang.reflect.ArtField
 class MANAGED ArtField : public Object {
  public:
+  static ArtField* FromReflectedField(const ScopedObjectAccess& soa, jobject jlr_field)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   Class* GetDeclaringClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void SetDeclaringClass(Class *new_declaring_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc
index 7814f36..ee5a0a4 100644
--- a/runtime/mirror/art_method.cc
+++ b/runtime/mirror/art_method.cc
@@ -16,6 +16,7 @@
 
 #include "art_method.h"
 
+#include "art_field-inl.h"
 #include "art_method-inl.h"
 #include "base/stringpiece.h"
 #include "class-inl.h"
@@ -28,8 +29,10 @@
 #include "object-inl.h"
 #include "object_array.h"
 #include "object_array-inl.h"
+#include "scoped_thread_state_change.h"
 #include "string.h"
 #include "object_utils.h"
+#include "well_known_classes.h"
 
 namespace art {
 namespace mirror {
@@ -45,6 +48,15 @@
 // TODO: get global references for these
 Class* ArtMethod::java_lang_reflect_ArtMethod_ = NULL;
 
+ArtMethod* ArtMethod::FromReflectedMethod(const ScopedObjectAccess& soa, jobject jlr_method) {
+  mirror::ArtField* f =
+      soa.DecodeField(WellKnownClasses::java_lang_reflect_AbstractMethod_artMethod);
+  mirror::ArtMethod* method = f->GetObject(soa.Decode<mirror::Object*>(jlr_method))->AsArtMethod();
+  DCHECK(method != nullptr);
+  return method;
+}
+
+
 void ArtMethod::VisitRoots(RootCallback* callback, void* arg) {
   if (java_lang_reflect_ArtMethod_ != nullptr) {
     callback(reinterpret_cast<mirror::Object**>(&java_lang_reflect_ArtMethod_), arg, 0,
diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h
index c654933..fd5ac19 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/mirror/art_method.h
@@ -31,6 +31,7 @@
 union JValue;
 struct MethodClassOffsets;
 class MethodHelper;
+class ScopedObjectAccess;
 class StringPiece;
 class ShadowFrame;
 
@@ -44,6 +45,9 @@
 // C++ mirror of java.lang.reflect.Method and java.lang.reflect.Constructor
 class MANAGED ArtMethod : public Object {
  public:
+  static ArtMethod* FromReflectedMethod(const ScopedObjectAccess& soa, jobject jlr_method)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   Class* GetDeclaringClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void SetDeclaringClass(Class *new_declaring_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/native/java_lang_reflect_Constructor.cc b/runtime/native/java_lang_reflect_Constructor.cc
index a22d7ca..b7e8ac2 100644
--- a/runtime/native/java_lang_reflect_Constructor.cc
+++ b/runtime/native/java_lang_reflect_Constructor.cc
@@ -36,10 +36,7 @@
  */
 static jobject Constructor_newInstance(JNIEnv* env, jobject javaMethod, jobjectArray javaArgs) {
   ScopedFastNativeObjectAccess soa(env);
-  jobject art_method = soa.Env()->GetObjectField(
-      javaMethod, WellKnownClasses::java_lang_reflect_AbstractMethod_artMethod);
-
-  mirror::ArtMethod* m = soa.Decode<mirror::Object*>(art_method)->AsArtMethod();
+  mirror::ArtMethod* m = mirror::ArtMethod::FromReflectedMethod(soa, javaMethod);
   SirtRef<mirror::Class> c(soa.Self(), m->GetDeclaringClass());
   if (UNLIKELY(c->IsAbstract())) {
     ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc
index 7e21d6c..6667d51 100644
--- a/runtime/native/java_lang_reflect_Field.cc
+++ b/runtime/native/java_lang_reflect_Field.cc
@@ -28,69 +28,72 @@
 namespace art {
 
 static bool GetFieldValue(const ScopedFastNativeObjectAccess& soa, mirror::Object* o,
-                          mirror::ArtField* f, JValue& value, bool allow_references)
+                          mirror::ArtField* f, Primitive::Type field_type, bool allow_references,
+                          JValue* value)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  DCHECK_EQ(value.GetJ(), INT64_C(0));
-  CHECK(!kMovingFields);
-  SirtRef<mirror::Object> sirt_obj(soa.Self(), o);
-  SirtRef<mirror::Class> sirt_klass(soa.Self(), f->GetDeclaringClass());
-  if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(sirt_klass, true, true)) {
-    return false;
-  }
-  o = sirt_obj.get();
-  switch (FieldHelper(f).GetTypeAsPrimitiveType()) {
-  case Primitive::kPrimBoolean:
-    value.SetZ(f->GetBoolean(o));
-    return true;
-  case Primitive::kPrimByte:
-    value.SetB(f->GetByte(o));
-    return true;
-  case Primitive::kPrimChar:
-    value.SetC(f->GetChar(o));
-    return true;
-  case Primitive::kPrimDouble:
-    value.SetD(f->GetDouble(o));
-    return true;
-  case Primitive::kPrimFloat:
-    value.SetF(f->GetFloat(o));
-    return true;
-  case Primitive::kPrimInt:
-    value.SetI(f->GetInt(o));
-    return true;
-  case Primitive::kPrimLong:
-    value.SetJ(f->GetLong(o));
-    return true;
-  case Primitive::kPrimShort:
-    value.SetS(f->GetShort(o));
-    return true;
-  case Primitive::kPrimNot:
-    if (allow_references) {
-      value.SetL(f->GetObject(o));
+  DCHECK_EQ(value->GetJ(), INT64_C(0));
+  DCHECK(f->GetDeclaringClass()->IsInitialized());
+  switch (field_type) {
+    case Primitive::kPrimBoolean:
+      value->SetZ(f->GetBoolean(o));
       return true;
-    }
-    // Else break to report an error.
-    break;
-  case Primitive::kPrimVoid:
-    // Never okay.
-    break;
+    case Primitive::kPrimByte:
+      value->SetB(f->GetByte(o));
+      return true;
+    case Primitive::kPrimChar:
+      value->SetC(f->GetChar(o));
+      return true;
+    case Primitive::kPrimDouble:
+      value->SetD(f->GetDouble(o));
+      return true;
+    case Primitive::kPrimFloat:
+      value->SetF(f->GetFloat(o));
+      return true;
+    case Primitive::kPrimInt:
+      value->SetI(f->GetInt(o));
+      return true;
+    case Primitive::kPrimLong:
+      value->SetJ(f->GetLong(o));
+      return true;
+    case Primitive::kPrimShort:
+      value->SetS(f->GetShort(o));
+      return true;
+    case Primitive::kPrimNot:
+      if (allow_references) {
+        value->SetL(f->GetObject(o));
+        return true;
+      }
+      // Else break to report an error.
+      break;
+    case Primitive::kPrimVoid:
+      // Never okay.
+      break;
   }
-  ThrowIllegalArgumentException(NULL,
-                                StringPrintf("Not a primitive field: %s",
-                                             PrettyField(f).c_str()).c_str());
+  ThrowIllegalArgumentException(nullptr, StringPrintf("Not a primitive field: %s",
+                                                      PrettyField(f).c_str()).c_str());
   return false;
 }
 
 static bool CheckReceiver(const ScopedFastNativeObjectAccess& soa, jobject j_rcvr,
-                          mirror::ArtField* f, mirror::Object*& class_or_rcvr)
+                          mirror::ArtField* f, mirror::Object** class_or_rcvr)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  soa.Self()->AssertThreadSuspensionIsAllowable();
   if (f->IsStatic()) {
-    class_or_rcvr = f->GetDeclaringClass();
+    SirtRef<mirror::Class> sirt_klass(soa.Self(), f->GetDeclaringClass());
+    if (UNLIKELY(!Runtime::Current()->GetClassLinker()->EnsureInitialized(sirt_klass, true, true))) {
+      DCHECK(soa.Self()->IsExceptionPending());
+      *class_or_rcvr = nullptr;
+      return false;
+    }
+    *class_or_rcvr = sirt_klass.get();
     return true;
   }
 
-  class_or_rcvr = soa.Decode<mirror::Object*>(j_rcvr);
+  *class_or_rcvr = soa.Decode<mirror::Object*>(j_rcvr);
   mirror::Class* declaringClass = f->GetDeclaringClass();
-  if (!VerifyObjectIsClass(class_or_rcvr, declaringClass)) {
+  if (!VerifyObjectIsClass(*class_or_rcvr, declaringClass)) {
+    DCHECK(soa.Self()->IsExceptionPending());
+    *class_or_rcvr = nullptr;
     return false;
   }
   return true;
@@ -98,42 +101,48 @@
 
 static jobject Field_get(JNIEnv* env, jobject javaField, jobject javaObj) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::ArtField* f = soa.DecodeField(env->FromReflectedField(javaField));
-  mirror::Object* o = NULL;
-  if (!CheckReceiver(soa, javaObj, f, o)) {
-    return NULL;
+  CHECK(!kMovingFields) << "CheckReceiver may trigger thread suspension for initialization";
+  mirror::ArtField* f = mirror::ArtField::FromReflectedField(soa, javaField);
+  mirror::Object* o = nullptr;
+  if (!CheckReceiver(soa, javaObj, f, &o)) {
+    DCHECK(soa.Self()->IsExceptionPending());
+    return nullptr;
   }
-
+  // We now don't expect suspension unless an exception is thrown.
   // Get the field's value, boxing if necessary.
+  Primitive::Type field_type = FieldHelper(f).GetTypeAsPrimitiveType();
   JValue value;
-  if (!GetFieldValue(soa, o, f, value, true)) {
-    return NULL;
+  if (!GetFieldValue(soa, o, f, field_type, true, &value)) {
+    DCHECK(soa.Self()->IsExceptionPending());
+    return nullptr;
   }
-  return
-      soa.AddLocalReference<jobject>(BoxPrimitive(FieldHelper(f).GetTypeAsPrimitiveType(), value));
+  return soa.AddLocalReference<jobject>(BoxPrimitive(field_type, value));
 }
 
 static JValue GetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj,
                                 char dst_descriptor) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::ArtField* f = soa.DecodeField(env->FromReflectedField(javaField));
-  mirror::Object* o = NULL;
-  if (!CheckReceiver(soa, javaObj, f, o)) {
+  CHECK(!kMovingFields) << "CheckReceiver may trigger thread suspension for initialization";
+  mirror::ArtField* f = mirror::ArtField::FromReflectedField(soa, javaField);
+  mirror::Object* o = nullptr;
+  if (!CheckReceiver(soa, javaObj, f, &o)) {
+    DCHECK(soa.Self()->IsExceptionPending());
     return JValue();
   }
-
+  // We now don't expect suspension unless an exception is thrown.
   // Read the value.
+  Primitive::Type field_type = FieldHelper(f).GetTypeAsPrimitiveType();
   JValue field_value;
-  if (!GetFieldValue(soa, o, f, field_value, false)) {
+  if (!GetFieldValue(soa, o, f, field_type, false, &field_value)) {
+    DCHECK(soa.Self()->IsExceptionPending());
     return JValue();
   }
 
   // Widen it if necessary (and possible).
   JValue wide_value;
-  mirror::Class* dst_type =
-      Runtime::Current()->GetClassLinker()->FindPrimitiveClass(dst_descriptor);
-  if (!ConvertPrimitiveValue(NULL, false, FieldHelper(f).GetTypeAsPrimitiveType(),
-                             dst_type->GetPrimitiveType(), field_value, wide_value)) {
+  if (!ConvertPrimitiveValue(NULL, false, field_type, Primitive::GetType(dst_descriptor),
+                             field_value, wide_value)) {
+    DCHECK(soa.Self()->IsExceptionPending());
     return JValue();
   }
   return wide_value;
@@ -172,16 +181,11 @@
 }
 
 static void SetFieldValue(ScopedFastNativeObjectAccess& soa, mirror::Object* o,
-                          mirror::ArtField* f, const JValue& new_value, bool allow_references)
+                          mirror::ArtField* f, Primitive::Type field_type, bool allow_references,
+                          const JValue& new_value)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  CHECK(!kMovingFields);
-  SirtRef<mirror::Object> sirt_obj(soa.Self(), o);
-  SirtRef<mirror::Class> sirt_klass(soa.Self(), f->GetDeclaringClass());
-  if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(sirt_klass, true, true)) {
-    return;
-  }
-  o = sirt_obj.get();
-  switch (FieldHelper(f).GetTypeAsPrimitiveType()) {
+  DCHECK(f->GetDeclaringClass()->IsInitialized());
+  switch (field_type) {
   case Primitive::kPrimBoolean:
     f->SetBoolean<false>(o, new_value.GetZ());
     break;
@@ -214,63 +218,77 @@
     // Else fall through to report an error.
   case Primitive::kPrimVoid:
     // Never okay.
-    ThrowIllegalArgumentException(NULL, StringPrintf("Not a primitive field: %s",
-                                                     PrettyField(f).c_str()).c_str());
+    ThrowIllegalArgumentException(nullptr, StringPrintf("Not a primitive field: %s",
+                                                        PrettyField(f).c_str()).c_str());
     return;
   }
-
-  // Special handling for final fields on SMP systems.
-  // We need a store/store barrier here (JMM requirement).
-  if (f->IsFinal()) {
-    QuasiAtomic::MembarStoreLoad();
-  }
 }
 
 static void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject javaValue) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::ArtField* f = soa.DecodeField(env->FromReflectedField(javaField));
-
+  CHECK(!kMovingFields) << "CheckReceiver may trigger thread suspension for initialization";
+  mirror::ArtField* f = mirror::ArtField::FromReflectedField(soa, javaField);
+  // Check that the receiver is non-null and an instance of the field's declaring class.
+  mirror::Object* o = nullptr;
+  if (!CheckReceiver(soa, javaObj, f, &o)) {
+    DCHECK(soa.Self()->IsExceptionPending());
+    return;
+  }
+  Primitive::Type field_prim_type;
+  mirror::Class* field_type;
+  {
+    FieldHelper fh(f);
+    const char* field_type_desciptor = fh.GetTypeDescriptor();
+    field_prim_type = Primitive::GetType(field_type_desciptor[0]);
+    if (field_prim_type == Primitive::kPrimNot) {
+      SirtRef<mirror::Object> sirt_obj(soa.Self(), o);
+      // May cause resolution.
+      CHECK(!kMovingFields) << "Resolution may trigger thread suspension";
+      field_type = fh.GetType(true);
+      if (field_type == nullptr) {
+        DCHECK(soa.Self()->IsExceptionPending());
+        return;
+      }
+    } else {
+      field_type = Runtime::Current()->GetClassLinker()->FindPrimitiveClass(field_type_desciptor[0]);
+    }
+  }
+  // We now don't expect suspension unless an exception is thrown.
   // Unbox the value, if necessary.
   mirror::Object* boxed_value = soa.Decode<mirror::Object*>(javaValue);
   JValue unboxed_value;
-  if (!UnboxPrimitiveForField(boxed_value, FieldHelper(f).GetType(), unboxed_value, f)) {
+  if (!UnboxPrimitiveForField(boxed_value, field_type, unboxed_value, f)) {
+    DCHECK(soa.Self()->IsExceptionPending());
     return;
   }
-
-  // Check that the receiver is non-null and an instance of the field's declaring class.
-  mirror::Object* o = NULL;
-  if (!CheckReceiver(soa, javaObj, f, o)) {
-    return;
-  }
-
-  SetFieldValue(soa, o, f, unboxed_value, true);
+  SetFieldValue(soa, o, f, field_prim_type, true, unboxed_value);
 }
 
 static void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, char src_descriptor,
                               const JValue& new_value) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::ArtField* f = soa.DecodeField(env->FromReflectedField(javaField));
-  mirror::Object* o = NULL;
-  if (!CheckReceiver(soa, javaObj, f, o)) {
+  mirror::ArtField* f = mirror::ArtField::FromReflectedField(soa, javaField);
+  mirror::Object* o = nullptr;
+  if (!CheckReceiver(soa, javaObj, f, &o)) {
     return;
   }
-  FieldHelper fh(f);
-  if (!fh.IsPrimitiveType()) {
-    ThrowIllegalArgumentException(NULL, StringPrintf("Not a primitive field: %s",
-                                                     PrettyField(f).c_str()).c_str());
+  Primitive::Type field_type = FieldHelper(f).GetTypeAsPrimitiveType();
+  if (UNLIKELY(field_type == Primitive::kPrimNot)) {
+    ThrowIllegalArgumentException(nullptr, StringPrintf("Not a primitive field: %s",
+                                                        PrettyField(f).c_str()).c_str());
     return;
   }
 
   // Widen the value if necessary (and possible).
   JValue wide_value;
-  mirror::Class* src_type = Runtime::Current()->GetClassLinker()->FindPrimitiveClass(src_descriptor);
-  if (!ConvertPrimitiveValue(NULL, false, src_type->GetPrimitiveType(), fh.GetTypeAsPrimitiveType(),
-                             new_value, wide_value)) {
+  if (!ConvertPrimitiveValue(nullptr, false, Primitive::GetType(src_descriptor),
+                             field_type, new_value, wide_value)) {
+    DCHECK(soa.Self()->IsExceptionPending());
     return;
   }
 
   // Write the value.
-  SetFieldValue(soa, o, f, wide_value, false);
+  SetFieldValue(soa, o, f, field_type, false, wide_value);
 }
 
 static void Field_setBoolean(JNIEnv* env, jobject javaField, jobject javaObj, jboolean z) {
diff --git a/runtime/native/java_lang_reflect_Method.cc b/runtime/native/java_lang_reflect_Method.cc
index 0b8bb7b..abb73b6 100644
--- a/runtime/native/java_lang_reflect_Method.cc
+++ b/runtime/native/java_lang_reflect_Method.cc
@@ -37,10 +37,7 @@
 
 static jobject Method_getExceptionTypesNative(JNIEnv* env, jobject javaMethod) {
   ScopedFastNativeObjectAccess soa(env);
-  jobject art_method = soa.Env()->GetObjectField(
-      javaMethod, WellKnownClasses::java_lang_reflect_AbstractMethod_artMethod);
-
-  mirror::ArtMethod* proxy_method = soa.Decode<mirror::Object*>(art_method)->AsArtMethod();
+  mirror::ArtMethod* proxy_method = mirror::ArtMethod::FromReflectedMethod(soa, javaMethod);
   CHECK(proxy_method->GetDeclaringClass()->IsProxyClass());
   mirror::SynthesizedProxyClass* proxy_class =
       down_cast<mirror::SynthesizedProxyClass*>(proxy_method->GetDeclaringClass());
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index dde9a94..f567055 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -462,8 +462,7 @@
 
 jobject InvokeMethod(const ScopedObjectAccess& soa, jobject javaMethod,
                      jobject javaReceiver, jobject javaArgs) {
-  jmethodID mid = soa.Env()->FromReflectedMethod(javaMethod);
-  mirror::ArtMethod* m = soa.DecodeMethod(mid);
+  mirror::ArtMethod* m = mirror::ArtMethod::FromReflectedMethod(soa, javaMethod);
 
   mirror::Class* declaring_class = m->GetDeclaringClass();
   if (UNLIKELY(!declaring_class->IsInitialized())) {