Implement Class.getDeclared(Constructors|Fields|Methods).

This required making sure that a Method* that represents a constructor
has java.lang.reflect.Constructor as its class.

Change-Id: I25908845a2b8d686d5404ac584693db0edd5853c
diff --git a/src/calling_convention_arm.cc b/src/calling_convention_arm.cc
index ae44b83..0a5868b 100644
--- a/src/calling_convention_arm.cc
+++ b/src/calling_convention_arm.cc
@@ -106,7 +106,7 @@
   size_t padding = 0;
   size_t check = method->IsStatic() ? 1 : 0;
   for(size_t i = 0; i < method->NumArgs(); i++) {
-    if(((i & 1) == check) && method->IsParamALongOrDouble(i)) {
+    if (((i & 1) == check) && method->IsParamALongOrDouble(i)) {
       padding += 4;
     }
   }
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 6daa27a..1c25f61 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -78,6 +78,7 @@
   "[Ljava/lang/Class;",
   "[Ljava/lang/Object;",
   "Ljava/lang/String;",
+  "Ljava/lang/reflect/Constructor;",
   "Ljava/lang/reflect/Field;",
   "Ljava/lang/reflect/Method;",
   "Ljava/lang/ClassLoader;",
@@ -252,7 +253,14 @@
     RegisterDexFile(*dex_file);
   }
 
-  // Field and Method are necessary so that FindClass can link members
+  // Constructor, Field, and Method are necessary so that FindClass can link members
+  Class* java_lang_reflect_Constructor = AllocClass(java_lang_Class, sizeof(MethodClass));
+  java_lang_reflect_Constructor->SetDescriptor(intern_table_->InternStrong("Ljava/lang/reflect/Constructor;"));
+  CHECK(java_lang_reflect_Constructor != NULL);
+  java_lang_reflect_Constructor->SetObjectSize(sizeof(Method));
+  SetClassRoot(kJavaLangReflectConstructor, java_lang_reflect_Constructor);
+  java_lang_reflect_Constructor->SetStatus(Class::kStatusResolved);
+
   Class* java_lang_reflect_Field = AllocClass(java_lang_Class, sizeof(FieldClass));
   CHECK(java_lang_reflect_Field != NULL);
   java_lang_reflect_Field->SetDescriptor(intern_table_->InternStrong("Ljava/lang/reflect/Field;"));
@@ -262,13 +270,12 @@
   Field::SetClass(java_lang_reflect_Field);
 
   Class* java_lang_reflect_Method = AllocClass(java_lang_Class, sizeof(MethodClass));
-  java_lang_reflect_Method->SetDescriptor(
-      intern_table_->InternStrong("Ljava/lang/reflect/Method;"));
+  java_lang_reflect_Method->SetDescriptor(intern_table_->InternStrong("Ljava/lang/reflect/Method;"));
   CHECK(java_lang_reflect_Method != NULL);
   java_lang_reflect_Method->SetObjectSize(sizeof(Method));
   SetClassRoot(kJavaLangReflectMethod, java_lang_reflect_Method);
   java_lang_reflect_Method->SetStatus(Class::kStatusResolved);
-  Method::SetClass(java_lang_reflect_Method);
+  Method::SetClasses(java_lang_reflect_Constructor, java_lang_reflect_Method);
 
   // now we can use FindSystemClass
 
@@ -337,11 +344,15 @@
   CHECK_EQ(java_lang_Cloneable, object_array_class->GetInterface(0));
   CHECK_EQ(java_io_Serializable, object_array_class->GetInterface(1));
 
-  // run Class, Field, and Method through FindSystemClass.
+  // run Class, Constructor, Field, and Method through FindSystemClass.
   // this initializes their dex_cache_ fields and register them in classes_.
   Class* Class_class = FindSystemClass("Ljava/lang/Class;");
   CHECK_EQ(java_lang_Class, Class_class);
 
+  java_lang_reflect_Constructor->SetStatus(Class::kStatusNotReady);
+  Class* Constructor_class = FindSystemClass("Ljava/lang/reflect/Constructor;");
+  CHECK_EQ(java_lang_reflect_Constructor, Constructor_class);
+
   java_lang_reflect_Field->SetStatus(Class::kStatusNotReady);
   Class* Field_class = FindSystemClass("Ljava/lang/reflect/Field;");
   CHECK_EQ(java_lang_reflect_Field, Field_class);
@@ -513,7 +524,7 @@
 
   String::SetClass(GetClassRoot(kJavaLangString));
   Field::SetClass(GetClassRoot(kJavaLangReflectField));
-  Method::SetClass(GetClassRoot(kJavaLangReflectMethod));
+  Method::SetClasses(GetClassRoot(kJavaLangReflectConstructor), GetClassRoot(kJavaLangReflectMethod));
   BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass));
   ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass));
   CharArray::SetArrayClass(GetClassRoot(kCharArrayClass));
@@ -594,7 +605,7 @@
 ClassLinker::~ClassLinker() {
   String::ResetClass();
   Field::ResetClass();
-  Method::ResetClass();
+  Method::ResetClasses();
   BooleanArray::ResetArrayClass();
   ByteArray::ResetArrayClass();
   CharArray::ResetArrayClass();
@@ -699,6 +710,8 @@
         klass = GetClassRoot(kJavaLangClass);
       } else if (descriptor == "Ljava/lang/String;") {
         klass = GetClassRoot(kJavaLangString);
+      } else if (descriptor == "Ljava/lang/reflect/Constructor;") {
+        klass = GetClassRoot(kJavaLangReflectConstructor);
       } else if (descriptor == "Ljava/lang/reflect/Field;") {
         klass = GetClassRoot(kJavaLangReflectField);
       } else if (descriptor == "Ljava/lang/reflect/Method;") {
@@ -957,7 +970,11 @@
                              Method* dst) {
   const DexFile::MethodId& method_id = dex_file.GetMethodId(src.method_idx_);
   dst->SetDeclaringClass(klass);
-  dst->SetName(ResolveString(dex_file, method_id.name_idx_, klass->GetDexCache()));
+  String* method_name = ResolveString(dex_file, method_id.name_idx_, klass->GetDexCache());
+  dst->SetName(method_name);
+  if (method_name->Equals("<init>")) {
+    dst->SetClass(GetClassRoot(kJavaLangReflectConstructor));
+  }
   {
     int32_t utf16_length;
     std::string utf8(dex_file.CreateMethodDescriptor(method_id.proto_idx_, &utf16_length));
diff --git a/src/class_linker.h b/src/class_linker.h
index 083d641..09736ce 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -317,6 +317,7 @@
     kClassArrayClass,
     kObjectArrayClass,
     kJavaLangString,
+    kJavaLangReflectConstructor,
     kJavaLangReflectField,
     kJavaLangReflectMethod,
     kJavaLangClassLoader,
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index c3b063c..ba67402 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -298,9 +298,9 @@
   CheckOffset(size_t c, const char* j) : cpp_offset(c), java_name(j) {}
 };
 
+template <typename T>
 struct CheckOffsets {
   bool instance;
-  size_t size;
   std::string class_descriptor;
   std::vector<CheckOffset> offsets;
 
@@ -312,11 +312,11 @@
 
     if (!klass->IsClassClass() && instance) {
       size_t expected_size = instance ? klass->GetObjectSize() : klass->GetClassSize();
-      if (size != expected_size) {
+      if (sizeof(T) != expected_size) {
         LG << "Class size mismatch:"
            << " class=" << class_descriptor
-           << " Java=" << klass->GetObjectSize()
-           << " C++=" << expected_size;
+           << " Java=" << expected_size
+           << " C++=" << sizeof(T);
         error = true;
       }
     }
@@ -376,10 +376,9 @@
 // Note that ClassLinkerTest.ValidateFieldOrderOfJavaCppUnionClasses
 // is first since if it is failing, others are unlikely to succeed.
 
-struct ObjectOffsets : public CheckOffsets {
+struct ObjectOffsets : public CheckOffsets<Object> {
   ObjectOffsets() {
     instance = true;
-    size = sizeof(Object);
     class_descriptor = "Ljava/lang/Object;";
 
     // alphabetical references
@@ -390,19 +389,17 @@
   };
 };
 
-struct AccessibleObjectOffsets : public CheckOffsets {
+struct AccessibleObjectOffsets : public CheckOffsets<AccessibleObject> {
   AccessibleObjectOffsets() {
     instance = true;
-    size = sizeof(AccessibleObject);
     class_descriptor = "Ljava/lang/reflect/AccessibleObject;";
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AccessibleObject, java_flag_), "flag"));
   };
 };
 
-struct FieldOffsets : public CheckOffsets {
+struct FieldOffsets : public CheckOffsets<Field> {
   FieldOffsets() {
     instance = true;
-    size = sizeof(Field);
     class_descriptor = "Ljava/lang/reflect/Field;";
 
     // alphabetical references
@@ -420,10 +417,9 @@
   };
 };
 
-struct MethodOffsets : public CheckOffsets {
+struct MethodOffsets : public CheckOffsets<Method> {
   MethodOffsets() {
     instance = true;
-    size = sizeof(Method);
     class_descriptor = "Ljava/lang/reflect/Method;";
 
     // alphabetical references
@@ -472,10 +468,16 @@
   };
 };
 
-struct ClassOffsets : public CheckOffsets {
+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 ClassOffsets : public CheckOffsets<Class> {
   ClassOffsets() {
     instance = true;
-    size = sizeof(Class);
     class_descriptor = "Ljava/lang/Class;";
 
     // alphabetical references
@@ -511,10 +513,9 @@
   };
 };
 
-struct StringOffsets : public CheckOffsets {
+struct StringOffsets : public CheckOffsets<String> {
   StringOffsets() {
     instance = true;
-    size = sizeof(String);
     class_descriptor = "Ljava/lang/String;";
 
     // alphabetical references
@@ -527,10 +528,9 @@
   };
 };
 
-struct ThrowableOffsets : public CheckOffsets {
+struct ThrowableOffsets : public CheckOffsets<Throwable> {
   ThrowableOffsets() {
     instance = true;
-    size = sizeof(Throwable);
     class_descriptor = "Ljava/lang/Throwable;";
 
     // alphabetical references
@@ -542,10 +542,9 @@
   };
 };
 
-struct StackTraceElementOffsets : public CheckOffsets {
+struct StackTraceElementOffsets : public CheckOffsets<StackTraceElement> {
   StackTraceElementOffsets() {
     instance = true;
-    size = sizeof(StackTraceElement);
     class_descriptor = "Ljava/lang/StackTraceElement;";
 
     // alphabetical references
@@ -556,10 +555,9 @@
   };
 };
 
-struct ClassLoaderOffsets : public CheckOffsets {
+struct ClassLoaderOffsets : public CheckOffsets<ClassLoader> {
   ClassLoaderOffsets() {
     instance = true;
-    size = sizeof(ClassLoader);
     class_descriptor = "Ljava/lang/ClassLoader;";
 
     // alphabetical references
@@ -568,10 +566,9 @@
   };
 };
 
-struct BaseDexClassLoaderOffsets : public CheckOffsets {
+struct BaseDexClassLoaderOffsets : public CheckOffsets<BaseDexClassLoader> {
   BaseDexClassLoaderOffsets() {
     instance = true;
-    size = sizeof(BaseDexClassLoader);
     class_descriptor = "Ldalvik/system/BaseDexClassLoader;";
 
     // alphabetical references
@@ -580,18 +577,16 @@
   };
 };
 
-struct PathClassLoaderOffsets : public CheckOffsets {
+struct PathClassLoaderOffsets : public CheckOffsets<PathClassLoader> {
   PathClassLoaderOffsets() {
     instance = true;
-    size = sizeof(PathClassLoader);
     class_descriptor = "Ldalvik/system/PathClassLoader;";
   };
 };
 
-struct ClassClassOffsets : public CheckOffsets {
+struct ClassClassOffsets : public CheckOffsets<ClassClass> {
   ClassClassOffsets() {
     instance = false;
-    size = sizeof(ClassClass);
     class_descriptor = "Ljava/lang/Class;";
 
     // padding 32-bit
@@ -603,10 +598,9 @@
   };
 };
 
-struct StringClassOffsets : public CheckOffsets {
+struct StringClassOffsets : public CheckOffsets<StringClass> {
   StringClassOffsets() {
     instance = false;
-    size = sizeof(StringClass);
     class_descriptor = "Ljava/lang/String;";
 
     // alphabetical references
@@ -621,10 +615,9 @@
   };
 };
 
-struct FieldClassOffsets : public CheckOffsets {
+struct FieldClassOffsets : public CheckOffsets<FieldClass> {
   FieldClassOffsets() {
     instance = false;
-    size = sizeof(FieldClass);
     class_descriptor = "Ljava/lang/reflect/Field;";
 
     // alphabetical references
@@ -642,10 +635,9 @@
   };
 };
 
-struct MethodClassOffsets : public CheckOffsets {
+struct MethodClassOffsets : public CheckOffsets<MethodClass> {
   MethodClassOffsets() {
     instance = false;
-    size = sizeof(MethodClass);
     class_descriptor = "Ljava/lang/reflect/Method;";
 
     // alphabetical references
@@ -660,6 +652,7 @@
 TEST_F(ClassLinkerTest, ValidateFieldOrderOfJavaCppUnionClasses) {
   EXPECT_TRUE(ObjectOffsets().Check());
   EXPECT_TRUE(AccessibleObjectOffsets().Check());
+  EXPECT_TRUE(ConstructorOffsets().Check());
   EXPECT_TRUE(FieldOffsets().Check());
   EXPECT_TRUE(MethodOffsets().Check());
   EXPECT_TRUE(ClassOffsets().Check());
diff --git a/src/compiler/codegen/CodegenFactory.cc b/src/compiler/codegen/CodegenFactory.cc
index 14c7e57..dbd9141 100644
--- a/src/compiler/codegen/CodegenFactory.cc
+++ b/src/compiler/codegen/CodegenFactory.cc
@@ -182,7 +182,7 @@
 {
     LIR* defStart;
     LIR* defEnd;
-    if(FPREG(rlSrc.lowReg)!=FPREG(rlSrc.highReg)) {
+    if (FPREG(rlSrc.lowReg)!=FPREG(rlSrc.highReg)) {
         LOG(WARNING) << "rlSrc.lowreg:" << rlSrc.lowReg << ", rlSrc.highReg:"
                      << rlSrc.highReg;
     }
diff --git a/src/java_lang_Class.cc b/src/java_lang_Class.cc
index c334f04..d77e3f0 100644
--- a/src/java_lang_Class.cc
+++ b/src/java_lang_Class.cc
@@ -18,6 +18,7 @@
 #include "class_linker.h"
 #include "class_loader.h"
 #include "object.h"
+#include "ScopedLocalRef.h"
 #include "ScopedUtfChars.h"
 
 #include "JniConstants.h" // Last to avoid problems with LOG redefinition.
@@ -53,6 +54,107 @@
   return AddLocalReference<jclass>(env, c);
 }
 
+template<typename T>
+jobjectArray ToArray(JNIEnv* env, const char* array_class_name, const std::vector<T*>& objects) {
+  jclass array_class = env->FindClass(array_class_name);
+  jobjectArray result = env->NewObjectArray(objects.size(), array_class, NULL);
+  for (size_t i = 0; i < objects.size(); ++i) {
+    ScopedLocalRef<jobject> object(env, AddLocalReference<jobject>(env, objects[i]));
+    env->SetObjectArrayElement(result, i, object.get());
+  }
+  return result;
+}
+
+bool IsVisibleConstructor(Method* m, bool public_only) {
+  if (public_only && !m->IsPublic()) {
+    return false;
+  }
+  if (m->IsMiranda() || m->IsStatic()) {
+    return false;
+  }
+  if (m->GetName()->CharAt(0) != '<') {
+    return false;
+  }
+  m->InitJavaFields();
+  return true;
+}
+
+jobjectArray Class_getDeclaredConstructors(JNIEnv* env, jclass, jclass javaClass, jboolean publicOnly) {
+  Class* c = Decode<Class*>(env, javaClass);
+
+  std::vector<Method*> constructors;
+  for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
+    Method* m = c->GetDirectMethod(i);
+    if (IsVisibleConstructor(m, publicOnly)) {
+      constructors.push_back(m);
+    }
+  }
+
+  return ToArray(env, "java/lang/reflect/Constructor", constructors);
+}
+
+bool IsVisibleField(Field* f, bool public_only) {
+  if (public_only && ~f->IsPublic()) {
+    return false;
+  }
+  f->InitJavaFields();
+  return true;
+}
+
+jobjectArray Class_getDeclaredFields(JNIEnv* env, jclass, jclass javaClass, jboolean publicOnly) {
+  Class* c = Decode<Class*>(env, javaClass);
+
+  std::vector<Field*> fields;
+  for (size_t i = 0; i < c->NumInstanceFields(); ++i) {
+    Field* f = c->GetInstanceField(i);
+    if (IsVisibleField(f, publicOnly)) {
+      fields.push_back(f);
+    }
+  }
+  for (size_t i = 0; i < c->NumStaticFields(); ++i) {
+    Field* f = c->GetStaticField(i);
+    if (IsVisibleField(f, publicOnly)) {
+      fields.push_back(f);
+    }
+  }
+
+  return ToArray(env, "java/lang/reflect/Field", fields);
+}
+
+bool IsVisibleMethod(Method* m, bool public_only) {
+  if (public_only && !m->IsPublic()) {
+    return false;
+  }
+  if (m->IsMiranda()) {
+    return false;
+  }
+  if (m->GetName()->CharAt(0) == '<') {
+    return false;
+  }
+  m->InitJavaFields();
+  return true;
+}
+
+jobjectArray Class_getDeclaredMethods(JNIEnv* env, jclass, jclass javaClass, jboolean publicOnly) {
+  Class* c = Decode<Class*>(env, javaClass);
+
+  std::vector<Method*> methods;
+  for (size_t i = 0; i < c->NumVirtualMethods(); ++i) {
+    Method* m = c->GetVirtualMethod(i);
+    if (IsVisibleMethod(m, publicOnly)) {
+      methods.push_back(m);
+    }
+  }
+  for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
+    Method* m = c->GetDirectMethod(i);
+    if (IsVisibleMethod(m, publicOnly)) {
+      methods.push_back(m);
+    }
+  }
+
+  return ToArray(env, "java/lang/reflect/Method", methods);
+}
+
 jboolean Class_desiredAssertionStatus(JNIEnv* env, jobject javaThis) {
     return JNI_FALSE;
 }
@@ -115,15 +217,17 @@
   String* name = Decode<String*>(env, jname);
   DCHECK(name->IsString());
 
-  for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
+  for (size_t i = 0; i < klass->NumInstanceFields(); ++i) {
     Field* f = klass->GetInstanceField(i);
     if (f->GetName()->Equals(name)) {
+      f->InitJavaFields();
       return AddLocalReference<jclass>(env, f);
     }
   }
   for (size_t i = 0; i < klass->NumStaticFields(); ++i) {
     Field* f = klass->GetStaticField(i);
     if (f->GetName()->Equals(name)) {
+      f->InitJavaFields();
       return AddLocalReference<jclass>(env, f);
     }
   }
@@ -319,10 +423,10 @@
   NATIVE_METHOD(Class, getClassLoader, "(Ljava/lang/Class;)Ljava/lang/ClassLoader;"),
   NATIVE_METHOD(Class, getComponentType, "()Ljava/lang/Class;"),
   NATIVE_METHOD(Class, getDeclaredConstructorOrMethod, "(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Member;"),
-  //NATIVE_METHOD(Class, getDeclaredConstructors, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Constructor;"),
+  NATIVE_METHOD(Class, getDeclaredConstructors, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Constructor;"),
   NATIVE_METHOD(Class, getDeclaredField, "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/reflect/Field;"),
-  //NATIVE_METHOD(Class, getDeclaredFields, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Field;"),
-  //NATIVE_METHOD(Class, getDeclaredMethods, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;"),
+  NATIVE_METHOD(Class, getDeclaredFields, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Field;"),
+  NATIVE_METHOD(Class, getDeclaredMethods, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;"),
   NATIVE_METHOD(Class, getDeclaringClass, "()Ljava/lang/Class;"),
   //NATIVE_METHOD(Class, getEnclosingClass, "()Ljava/lang/Class;"),
   NATIVE_METHOD(Class, getEnclosingConstructor, "()Ljava/lang/reflect/Constructor;"),
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 96b3b34..8bc5081 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -341,9 +341,7 @@
         name, class_descriptor.c_str());
     return NULL;
   }
-  // Check invariant that all jfieldIDs have resolved types (how else would
-  // the type equality in Find...Field hold?)
-  DCHECK(field->GetType() != NULL);
+  field->InitJavaFields();
   return EncodeField(field);
 }
 
diff --git a/src/object.cc b/src/object.cc
index 7b47d9f..f47f16e 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -103,8 +103,24 @@
 }
 
 Class* Field::GetType() const {
-  // Do full linkage (which sets dex cache value to speed next call)
-  return Runtime::Current()->GetClassLinker()->ResolveType(GetTypeIdx(), this);
+  if (type_ == NULL) {
+    type_ = Runtime::Current()->GetClassLinker()->ResolveType(GetTypeIdx(), this);
+  }
+  return type_;
+}
+
+void Field::InitJavaFields() {
+  Thread* self = Thread::Current();
+  ScopedThreadStateChange tsc(self, Thread::kRunnable);
+  MonitorEnter(self);
+  if (type_ == NULL) {
+    InitJavaFieldsLocked();
+  }
+  MonitorExit(self);
+}
+
+void Field::InitJavaFieldsLocked() {
+  GetType(); // Sets type_ as a side-effect. May throw.
 }
 
 Field* Field::FindInstanceFieldFromCode(uint32_t field_idx, const Method* referrer) {
@@ -308,15 +324,23 @@
 }
 
 // TODO: get global references for these
+Class* Method::java_lang_reflect_Constructor_ = NULL;
 Class* Method::java_lang_reflect_Method_ = NULL;
 
-void Method::SetClass(Class* java_lang_reflect_Method) {
+void Method::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;
+
   CHECK(java_lang_reflect_Method_ == NULL);
   CHECK(java_lang_reflect_Method != NULL);
   java_lang_reflect_Method_ = java_lang_reflect_Method;
 }
 
-void Method::ResetClass() {
+void Method::ResetClasses() {
+  CHECK(java_lang_reflect_Constructor_ != NULL);
+  java_lang_reflect_Constructor_ = NULL;
+
   CHECK(java_lang_reflect_Method_ != NULL);
   java_lang_reflect_Method_ = NULL;
 }
@@ -648,7 +672,7 @@
        !iter.HasNext(); iter.Next()) {
     uint32_t iter_type_idx = iter.Get().type_idx_;
     // Catch all case
-    if(iter_type_idx == DexFile::kDexNoIndex) {
+    if (iter_type_idx == DexFile::kDexNoIndex) {
       return iter.Get().address_;
     }
     // Does this catch exception type apply?
@@ -1186,6 +1210,19 @@
   return Alloc(array_class, component_count, array_class->GetComponentSize());
 }
 
+bool Array::ThrowArrayIndexOutOfBoundsException(int32_t index) const {
+  Thread::Current()->ThrowNewException("Ljava/lang/ArrayIndexOutOfBoundsException;",
+      "length=%i; index=%i", length_, index);
+  return false;
+}
+
+bool Array::ThrowArrayStoreException(Object* object) const {
+  Thread::Current()->ThrowNewException("Ljava/lang/ArrayStoreException;",
+      "Can't store an element of type %s into an array of type %s",
+      PrettyTypeOf(object).c_str(), PrettyTypeOf(this).c_str());
+  return false;
+}
+
 template<typename T>
 PrimitiveArray<T>* PrimitiveArray<T>::Alloc(size_t length) {
   DCHECK(array_class_ != NULL);
diff --git a/src/object.h b/src/object.h
index 69f8c14..ba8aaa9 100644
--- a/src/object.h
+++ b/src/object.h
@@ -442,12 +442,16 @@
                false);
   }
 
+  bool IsPublic() const {
+    return (GetAccessFlags() & kAccPublic) != 0;
+  }
+
   bool IsStatic() const {
     return (GetAccessFlags() & kAccStatic) != 0;
   }
 
   bool IsFinal() const {
-    return (access_flags_ & kAccFinal) != 0;
+    return (GetAccessFlags() & kAccFinal) != 0;
   }
 
   uint32_t GetTypeIdx() const;
@@ -524,6 +528,8 @@
     return (GetAccessFlags() & kAccVolatile) != 0;
   }
 
+  void InitJavaFields();
+
  private:
   // private implementation of field access using raw data
   uint32_t Get32(const Object* object) const;
@@ -533,6 +539,8 @@
   Object* GetObj(const Object* object) const;
   void SetObj(Object* object, const Object* new_value) const;
 
+  void InitJavaFieldsLocked();
+
   // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
 
   // The class in which this field is declared.
@@ -543,7 +551,7 @@
   const String* name_;
 
   // Type of the field
-  Class* type_;
+  mutable Class* type_;
 
   uint32_t generic_types_are_initialized_;
 
@@ -642,17 +650,18 @@
     return (GetAccessFlags() & synchonized) != 0;
   }
 
-  // Returns true if the method is declared final.
   bool IsFinal() const {
     return (GetAccessFlags() & kAccFinal) != 0;
   }
 
-  // Returns true if the method is declared native.
+  bool IsMiranda() const {
+    return (GetAccessFlags() & kAccMiranda) != 0;
+  }
+
   bool IsNative() const {
     return (GetAccessFlags() & kAccNative) != 0;
   }
 
-  // Returns true if the method is declared abstract.
   bool IsAbstract() const {
     return (GetAccessFlags() & kAccAbstract) != 0;
   }
@@ -947,14 +956,17 @@
   // Find the catch block for the given exception type and dex_pc
   uint32_t FindCatchBlock(Class* exception_type, uint32_t dex_pc) const;
 
-  static Class* GetJavaLangReflectMethod() {
-    DCHECK(java_lang_reflect_Method_ != NULL);
+  static void SetClasses(Class* java_lang_reflect_Constructor, Class* java_lang_reflect_Method);
+
+  static Class* GetConstructorClass() {
+    return java_lang_reflect_Constructor_;
+  }
+
+  static Class* GetMethodClass() {
     return java_lang_reflect_Method_;
   }
 
-  static void SetClass(Class* java_lang_reflect_Method);
-  static Class* GetMethodClass() { return java_lang_reflect_Method_; }
-  static void ResetClass();
+  static void ResetClasses();
 
   void InitJavaFields();
 
@@ -1079,6 +1091,7 @@
 
   uint32_t java_slot_;
 
+  static Class* java_lang_reflect_Constructor_;
   static Class* java_lang_reflect_Method_;
 
   friend class ImageWriter;  // for relocating code_ and invoke_stub_
@@ -1125,14 +1138,15 @@
  protected:
   bool IsValidIndex(int32_t index) const {
     if (index < 0 || index >= length_) {
-      Thread* self = Thread::Current();
-      self->ThrowNewException("Ljava/lang/ArrayIndexOutOfBoundsException;",
-          "length=%i; index=%i", length_, index);
-      return false;
+      return ThrowArrayIndexOutOfBoundsException(index);
     }
     return true;
   }
 
+ protected:
+  bool ThrowArrayIndexOutOfBoundsException(int32_t index) const;
+  bool ThrowArrayStoreException(Object* object) const;
+
  private:
   // The number of array elements.
   int32_t length_;
@@ -2097,10 +2111,8 @@
 }
 
 inline bool Object::IsMethod() const {
-  Class* java_lang_Class = GetClass()->GetClass();
-  Class* java_lang_reflect_Method =
-      java_lang_Class->GetDirectMethod(0)->GetClass();
-  return GetClass() == java_lang_reflect_Method;
+  Class* c = GetClass();
+  return c == Method::GetMethodClass() || c == Method::GetConstructorClass();
 }
 
 inline bool Object::IsReferenceInstance() const {
@@ -2209,9 +2221,10 @@
   if (IsValidIndex(i)) {
     if (object != NULL) {
       Class* element_class = GetClass()->GetComponentType();
-      DCHECK(!element_class->IsPrimitive());
-      // TODO: ArrayStoreException
-      CHECK(object->InstanceOf(element_class));
+      if (!object->InstanceOf(element_class)) {
+        ThrowArrayStoreException(object);
+        return;
+      }
     }
     MemberOffset data_offset(DataOffset().Int32Value() + i * sizeof(Object*));
     SetFieldObject(data_offset, object, false);
@@ -2251,8 +2264,10 @@
       CHECK(!element_class->IsPrimitive());
       for (size_t i=0; i < length; i++) {
         Object* object = src->GetFieldObject<Object*>(src_offset, false);
-        // TODO: ArrayStoreException
-        CHECK(object == NULL || object->InstanceOf(element_class));
+        if (object != NULL && !object->InstanceOf(element_class)) {
+          dst->ThrowArrayStoreException(object);
+          return;
+        }
         dst->SetFieldObject(dst_offset, object, false);
         src_offset = MemberOffset(src_offset.Uint32Value() + sizeof(Object*));
         dst_offset = MemberOffset(dst_offset.Uint32Value() + sizeof(Object*));
@@ -2567,9 +2582,10 @@
   // Check class is loaded or this is java.lang.String that has a
   // circularity issue during loading the names of its members
   DCHECK(IsLoaded() || IsErroneous() ||
-         this == String::GetJavaLangString() ||
-         this == Field::GetJavaLangReflectField() ||
-         this == Method::GetJavaLangReflectMethod()) << PrettyClass(this);
+      this == String::GetJavaLangString() ||
+      this == Field::GetJavaLangReflectField() ||
+      this == Method::GetConstructorClass() ||
+      this == Method::GetMethodClass()) << PrettyClass(this);
   return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), false);
 }
 
diff --git a/src/thread.cc b/src/thread.cc
index 8005072..71b9090 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -484,8 +484,9 @@
   DCHECK_LT(frame_size, 1024u);
   byte* next_sp = reinterpret_cast<byte*>(sp_) + frame_size;
   sp_ = reinterpret_cast<Method**>(next_sp);
-  if(*sp_ != NULL) {
-    DCHECK_EQ((*sp_)->GetClass(), Method::GetMethodClass());
+  if (*sp_ != NULL) {
+    DCHECK((*sp_)->GetClass() == Method::GetMethodClass() ||
+        (*sp_)->GetClass() == Method::GetConstructorClass());
   }
 }