Change Class::component_type_ and implement reflect.Array

Change-Id: I9e06f31577551c738eca2621146c8d2328119442
diff --git a/build/Android.common.mk b/build/Android.common.mk
index ae96dab..94c7b15 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -106,6 +106,7 @@
 	src/java_lang_System.cc \
 	src/java_lang_Thread.cc \
 	src/java_lang_Throwable.cc \
+	src/java_lang_reflect_Array.cc \
 	src/java_lang_reflect_Field.cc \
 	src/java_lang_reflect_Method.cc \
 	src/java_util_concurrent_atomic_AtomicLong.cc \
diff --git a/src/class_linker.cc b/src/class_linker.cc
index e3b4eea..0f02d09 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -129,12 +129,14 @@
 
   // Object[] next to hold class roots
   Class* object_array_class = AllocClass(java_lang_Class, sizeof(Class));
-  object_array_class->SetArrayRank(1);
   object_array_class->SetComponentType(java_lang_Object);
 
+  // Setup the char class to be used for char[]
+  Class* char_class = AllocClass(java_lang_Class, sizeof(Class));
+
   // Setup the char[] class to be used for String
   Class* char_array_class = AllocClass(java_lang_Class, sizeof(Class));
-  char_array_class->SetArrayRank(1);
+  char_array_class->SetComponentType(char_class);
   CharArray::SetArrayClass(char_array_class);
 
   // Setup String
@@ -162,7 +164,6 @@
   // Setup the primitive type classes.
   SetClassRoot(kPrimitiveBoolean, CreatePrimitiveClass("Z", Class::kPrimBoolean));
   SetClassRoot(kPrimitiveByte, CreatePrimitiveClass("B", Class::kPrimByte));
-  SetClassRoot(kPrimitiveChar, CreatePrimitiveClass("C", Class::kPrimChar));
   SetClassRoot(kPrimitiveShort, CreatePrimitiveClass("S", Class::kPrimShort));
   SetClassRoot(kPrimitiveInt, CreatePrimitiveClass("I", Class::kPrimInt));
   SetClassRoot(kPrimitiveLong, CreatePrimitiveClass("J", Class::kPrimLong));
@@ -170,16 +171,12 @@
   SetClassRoot(kPrimitiveDouble, CreatePrimitiveClass("D", Class::kPrimDouble));
   SetClassRoot(kPrimitiveVoid, CreatePrimitiveClass("V", Class::kPrimVoid));
 
-  // Backfill component type of char[]
-  char_array_class->SetComponentType(GetClassRoot(kPrimitiveChar));
-
   // Create array interface entries to populate once we can load system classes
   array_interfaces_ = AllocObjectArray<Class>(2);
   array_iftable_ = AllocObjectArray<InterfaceEntry>(2);
 
   // Create int array type for AllocDexCache (done in AppendToBootClassPath)
   Class* int_array_class = AllocClass(java_lang_Class, sizeof(Class));
-  int_array_class->SetArrayRank(1);
   int_array_class->SetDescriptor(intern_table_->InternStrong("[I"));
   int_array_class->SetComponentType(GetClassRoot(kPrimitiveInt));
   IntArray::SetArrayClass(int_array_class);
@@ -220,6 +217,10 @@
 
   // now we can use FindSystemClass
 
+  // run char class through InitializePrimitiveClass to finish init
+  InitializePrimitiveClass(char_class, "C", Class::kPrimChar);
+  SetClassRoot(kPrimitiveChar, char_class);  // needs descriptor
+
   // Object and String need to be rerun through FindSystemClass to finish init
   java_lang_Object->SetStatus(Class::kStatusNotReady);
   Class* Object_class = FindSystemClass("Ljava/lang/Object;");
@@ -614,7 +615,7 @@
   Class* klass = LookupClass(descriptor, class_loader);
   if (klass == NULL) {
     // Class is not yet loaded.
-    if (descriptor[0] == '[') {
+    if (descriptor[0] == '[' && descriptor[1] != '\0') {
       return CreateArrayClass(descriptor, class_loader);
     }
     const DexFile::ClassPath& class_path = ((class_loader != NULL)
@@ -979,18 +980,18 @@
   return NULL;
 }
 
-Class* ClassLinker::CreatePrimitiveClass(const char* descriptor,
-                                         Class::PrimitiveType type) {
+Class* ClassLinker::InitializePrimitiveClass(Class* primitive_class,
+                                             const char* descriptor,
+                                             Class::PrimitiveType type) {
   // TODO: deduce one argument from the other
-  Class* klass = AllocClass(sizeof(Class));
-  CHECK(klass != NULL);
-  klass->SetAccessFlags(kAccPublic | kAccFinal | kAccAbstract);
-  klass->SetDescriptor(intern_table_->InternStrong(descriptor));
-  klass->SetPrimitiveType(type);
-  klass->SetStatus(Class::kStatusInitialized);
-  bool success = InsertClass(descriptor, klass);
-  CHECK(success) << "CreatePrimitiveClass(" << descriptor << ") failed";
-  return klass;
+  CHECK(primitive_class != NULL);
+  primitive_class->SetAccessFlags(kAccPublic | kAccFinal | kAccAbstract);
+  primitive_class->SetDescriptor(intern_table_->InternStrong(descriptor));
+  primitive_class->SetPrimitiveType(type);
+  primitive_class->SetStatus(Class::kStatusInitialized);
+  bool success = InsertClass(descriptor, primitive_class);
+  CHECK(success) << "InitPrimitiveClass(" << descriptor << ") failed";
+  return primitive_class;
 }
 
 // Create an array class (i.e. the class object for the array, not the
@@ -1000,44 +1001,20 @@
 // If "descriptor" refers to an array of primitives, look up the
 // primitive type's internally-generated class object.
 //
-// "loader" is the class loader of the class that's referring to us.  It's
-// used to ensure that we're looking for the element type in the right
-// context.  It does NOT become the class loader for the array class; that
-// always comes from the base element class.
+// "class_loader" is the class loader of the class that's referring to
+// us.  It's used to ensure that we're looking for the element type in
+// the right context.  It does NOT become the class loader for the
+// array class; that always comes from the base element class.
 //
 // Returns NULL with an exception raised on failure.
 Class* ClassLinker::CreateArrayClass(const StringPiece& descriptor,
                                      const ClassLoader* class_loader) {
   CHECK_EQ('[', descriptor[0]);
 
-  // Identify the underlying element class and the array dimension depth.
-  Class* component_type = NULL;
-  int array_rank;
-  if (descriptor[1] == '[') {
-    // array of arrays; keep descriptor and grab stuff from parent
-    Class* outer = FindClass(descriptor.substr(1), class_loader);
-    if (outer != NULL) {
-      // want the base class, not "outer", in our component_type
-      component_type = outer->GetComponentType();
-      array_rank = outer->GetArrayRank() + 1;
-    } else {
-      DCHECK(component_type == NULL);  // make sure we fail
-    }
-  } else {
-    array_rank = 1;
-    if (descriptor[1] == 'L') {
-      // array of objects; strip off "[" and look up descriptor.
-      const StringPiece subDescriptor = descriptor.substr(1);
-      component_type = FindClass(subDescriptor, class_loader);
-    } else {
-      // array of a primitive type
-      component_type = FindPrimitiveClass(descriptor[1]);
-    }
-  }
-
+  // Identify the underlying component type
+  Class* component_type = FindClass(descriptor.substr(1), class_loader);
   if (component_type == NULL) {
-    // failed
-    // DCHECK(Thread::Current()->IsExceptionPending());  // TODO
+    DCHECK(Thread::Current()->IsExceptionPending());
     return NULL;
   }
 
@@ -1090,10 +1067,8 @@
     if (new_class == NULL) {
       return NULL;
     }
-    new_class->SetArrayRank(array_rank);
     new_class->SetComponentType(component_type);
   }
-  DCHECK_LE(1, new_class->GetArrayRank());
   DCHECK(new_class->GetComponentType() != NULL);
   if (new_class->GetDescriptor() != NULL) {
     DCHECK(new_class->GetDescriptor()->Equals(descriptor));
diff --git a/src/class_linker.h b/src/class_linker.h
index 53291b5..02e6d6f 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -193,7 +193,13 @@
   InterfaceEntry* AllocInterfaceEntry(Class* interface);
 
   Class* CreatePrimitiveClass(const char* descriptor,
-                              Class::PrimitiveType type);
+                              Class::PrimitiveType type) {
+    return InitializePrimitiveClass(AllocClass(sizeof(Class)), descriptor, type);
+  }
+  Class* InitializePrimitiveClass(Class* primitive_class,
+                                  const char* descriptor,
+                                  Class::PrimitiveType type);
+
 
   Class* CreateArrayClass(const StringPiece& descriptor,
                           const ClassLoader* class_loader);
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index 32f2eec..5e605c4 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -43,7 +43,7 @@
     EXPECT_TRUE(primitive->IsResolved());
     EXPECT_FALSE(primitive->IsArrayInstance());
     EXPECT_FALSE(primitive->IsArrayClass());
-    EXPECT_EQ(0, primitive->GetArrayRank());
+    EXPECT_TRUE(primitive->GetComponentType() == NULL);
     EXPECT_FALSE(primitive->IsInterface());
     EXPECT_TRUE(primitive->IsPublic());
     EXPECT_TRUE(primitive->IsFinal());
@@ -60,11 +60,9 @@
   }
 
   void AssertArrayClass(const StringPiece& array_descriptor,
-                        int32_t array_rank,
                         const StringPiece& component_type,
                         const ClassLoader* class_loader) {
     Class* array = class_linker_->FindClass(array_descriptor, class_loader);
-    EXPECT_EQ(array_rank, array->GetArrayRank());
     EXPECT_TRUE(array->GetComponentType()->GetDescriptor()->Equals(component_type));
     EXPECT_EQ(class_loader, array->GetClassLoader());
     AssertArrayClass(array_descriptor, array);
@@ -87,7 +85,6 @@
     EXPECT_TRUE(array->IsResolved());
     EXPECT_FALSE(array->IsArrayInstance());
     EXPECT_TRUE(array->IsArrayClass());
-    EXPECT_LE(1, array->GetArrayRank());
     EXPECT_FALSE(array->IsInterface());
     EXPECT_EQ(array->GetComponentType()->IsPublic(), array->IsPublic());
     EXPECT_TRUE(array->IsFinal());
@@ -156,7 +153,7 @@
     EXPECT_TRUE(klass->IsResolved());
     EXPECT_TRUE(klass->IsLoaded());
     EXPECT_FALSE(klass->IsArrayClass());
-    EXPECT_EQ(0, klass->GetArrayRank());
+    EXPECT_TRUE(klass->GetComponentType() == NULL);
     EXPECT_TRUE(klass->IsInSamePackage(klass));
     EXPECT_TRUE(Class::IsInSamePackage(klass->GetDescriptor(), klass->GetDescriptor()));
     if (klass->IsInterface()) {
@@ -292,113 +289,6 @@
   }
 };
 
-TEST_F(ClassLinkerTest, FindClassNonexistent) {
-  AssertNonExistentClass("NoSuchClass;");
-  AssertNonExistentClass("LNoSuchClass;");
-}
-
-TEST_F(ClassLinkerTest, FindClassNested) {
-  const ClassLoader* class_loader = LoadDex("Nested");
-
-  Class* outer = class_linker_->FindClass("LNested;", class_loader);
-  ASSERT_TRUE(outer != NULL);
-  EXPECT_EQ(0U, outer->NumVirtualMethods());
-  EXPECT_EQ(1U, outer->NumDirectMethods());
-
-  Class* inner = class_linker_->FindClass("LNested$Inner;", class_loader);
-  ASSERT_TRUE(inner != NULL);
-  EXPECT_EQ(0U, inner->NumVirtualMethods());
-  EXPECT_EQ(1U, inner->NumDirectMethods());
-}
-
-TEST_F(ClassLinkerTest, FindClass_Primitives) {
-  StringPiece expected = "BCDFIJSZV";
-  for (int ch = 0; ch < 255; ch++) {
-    char* s = reinterpret_cast<char*>(&ch);
-    StringPiece descriptor(s, 1);
-    if (expected.find(ch) == StringPiece::npos) {
-      AssertNonExistentClass(descriptor);
-    } else {
-      AssertPrimitiveClass(descriptor);
-    }
-  }
-}
-
-TEST_F(ClassLinkerTest, FindClass) {
-  Class* JavaLangObject = class_linker_->FindSystemClass("Ljava/lang/Object;");
-  ASSERT_TRUE(JavaLangObject != NULL);
-  ASSERT_TRUE(JavaLangObject->GetClass() != NULL);
-  ASSERT_EQ(JavaLangObject->GetClass(), JavaLangObject->GetClass()->GetClass());
-  EXPECT_EQ(JavaLangObject, JavaLangObject->GetClass()->GetSuperClass());
-  ASSERT_TRUE(JavaLangObject->GetDescriptor()->Equals("Ljava/lang/Object;"));
-  EXPECT_TRUE(JavaLangObject->GetSuperClass() == NULL);
-  EXPECT_FALSE(JavaLangObject->HasSuperClass());
-  EXPECT_TRUE(JavaLangObject->GetClassLoader() == NULL);
-  EXPECT_FALSE(JavaLangObject->IsErroneous());
-  EXPECT_TRUE(JavaLangObject->IsVerified());
-  EXPECT_TRUE(JavaLangObject->IsResolved());
-  EXPECT_FALSE(JavaLangObject->IsArrayInstance());
-  EXPECT_FALSE(JavaLangObject->IsArrayClass());
-  EXPECT_EQ(0, JavaLangObject->GetArrayRank());
-  EXPECT_FALSE(JavaLangObject->IsInterface());
-  EXPECT_TRUE(JavaLangObject->IsPublic());
-  EXPECT_FALSE(JavaLangObject->IsFinal());
-  EXPECT_FALSE(JavaLangObject->IsPrimitive());
-  EXPECT_FALSE(JavaLangObject->IsSynthetic());
-  EXPECT_EQ(2U, JavaLangObject->NumDirectMethods());
-  EXPECT_EQ(11U, JavaLangObject->NumVirtualMethods());
-  EXPECT_EQ(2U, JavaLangObject->NumInstanceFields());
-  EXPECT_TRUE(JavaLangObject->GetInstanceField(0)->GetName()->Equals("shadow$_klass_"));
-  EXPECT_TRUE(JavaLangObject->GetInstanceField(1)->GetName()->Equals("shadow$_monitor_"));
-
-  EXPECT_EQ(0U, JavaLangObject->NumStaticFields());
-  EXPECT_EQ(0U, JavaLangObject->NumInterfaces());
-
-  const ClassLoader* class_loader = LoadDex("MyClass");
-  AssertNonExistentClass("LMyClass;");
-  Class* MyClass = class_linker_->FindClass("LMyClass;", class_loader);
-  ASSERT_TRUE(MyClass != NULL);
-  ASSERT_TRUE(MyClass->GetClass() != NULL);
-  ASSERT_EQ(MyClass->GetClass(), MyClass->GetClass()->GetClass());
-  EXPECT_EQ(JavaLangObject, MyClass->GetClass()->GetSuperClass());
-  ASSERT_TRUE(MyClass->GetDescriptor()->Equals("LMyClass;"));
-  EXPECT_TRUE(MyClass->GetSuperClass() == JavaLangObject);
-  EXPECT_TRUE(MyClass->HasSuperClass());
-  EXPECT_EQ(class_loader, MyClass->GetClassLoader());
-  EXPECT_TRUE(MyClass->GetStatus() == Class::kStatusResolved);
-  EXPECT_FALSE(MyClass->IsErroneous());
-  EXPECT_FALSE(MyClass->IsVerified());
-  EXPECT_TRUE(MyClass->IsResolved());
-  EXPECT_FALSE(MyClass->IsArrayInstance());
-  EXPECT_FALSE(MyClass->IsArrayClass());
-  EXPECT_EQ(0, JavaLangObject->GetArrayRank());
-  EXPECT_FALSE(MyClass->IsInterface());
-  EXPECT_FALSE(MyClass->IsPublic());
-  EXPECT_FALSE(MyClass->IsFinal());
-  EXPECT_FALSE(MyClass->IsPrimitive());
-  EXPECT_FALSE(MyClass->IsSynthetic());
-  EXPECT_EQ(1U, MyClass->NumDirectMethods());
-  EXPECT_EQ(0U, MyClass->NumVirtualMethods());
-  EXPECT_EQ(0U, MyClass->NumInstanceFields());
-  EXPECT_EQ(0U, MyClass->NumStaticFields());
-  EXPECT_EQ(0U, MyClass->NumInterfaces());
-
-  EXPECT_EQ(JavaLangObject->GetClass()->GetClass(), MyClass->GetClass()->GetClass());
-
-  // created by class_linker
-  AssertArrayClass("[C", 1, "C", NULL);
-  AssertArrayClass("[Ljava/lang/Object;", 1, "Ljava/lang/Object;", NULL);
-  // synthesized on the fly
-  AssertArrayClass("[[C", 2, "C", NULL);
-  AssertArrayClass("[[[LMyClass;", 3, "LMyClass;", class_loader);
-  // or not available at all
-  AssertNonExistentClass("[[[[LNonExistentClass;");
-}
-
-TEST_F(ClassLinkerTest, LibCore) {
-  AssertDexFile(java_lang_dex_file_.get(), NULL);
-}
-
 struct CheckOffset {
   size_t cpp_offset;
   const char* java_name;
@@ -480,6 +370,9 @@
   };
 };
 
+// Note that ClassLinkerTest.ValidateFieldOrderOfJavaCppUnionClasses
+// is first since if it is failing, others are unlikely to succeed.
+
 struct ObjectOffsets : public CheckOffsets {
   ObjectOffsets() {
     instance = true;
@@ -601,7 +494,6 @@
 
     // alphabetical 32-bit
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, access_flags_),                  "shadow$_access_flags_"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, array_rank_),                    "shadow$_array_rank_"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, class_size_),                    "shadow$_class_size_"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, clinit_thread_id_),              "shadow$_clinit_thread_id_"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, num_reference_instance_fields_), "shadow$_num_reference_instance_fields_"));
@@ -698,6 +590,10 @@
     size = sizeof(ClassClass);
     class_descriptor = "Ljava/lang/Class;";
 
+    // padding 32-bit
+    CHECK_EQ(OFFSETOF_MEMBER(ClassClass, padding_) + 4,
+             OFFSETOF_MEMBER(ClassClass, serialVersionUID_));
+
     // alphabetical 64-bit
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(ClassClass, serialVersionUID_), "serialVersionUID"));
   };
@@ -713,11 +609,11 @@
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(StringClass, ASCII_),                  "ASCII"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(StringClass, CASE_INSENSITIVE_ORDER_), "CASE_INSENSITIVE_ORDER"));
 
+    // padding 32-bit
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(StringClass, REPLACEMENT_CHAR_),       "REPLACEMENT_CHAR"));
+
     // alphabetical 64-bit
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(StringClass, serialVersionUID_),       "serialVersionUID"));
-
-    // alphabetical 32-bit
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(StringClass, REPLACEMENT_CHAR_),       "REPLACEMENT_CHAR"));
   };
 };
 
@@ -776,6 +672,113 @@
   EXPECT_TRUE(MethodClassOffsets().Check());
 }
 
+TEST_F(ClassLinkerTest, FindClassNonexistent) {
+  AssertNonExistentClass("NoSuchClass;");
+  AssertNonExistentClass("LNoSuchClass;");
+}
+
+TEST_F(ClassLinkerTest, FindClassNested) {
+  const ClassLoader* class_loader = LoadDex("Nested");
+
+  Class* outer = class_linker_->FindClass("LNested;", class_loader);
+  ASSERT_TRUE(outer != NULL);
+  EXPECT_EQ(0U, outer->NumVirtualMethods());
+  EXPECT_EQ(1U, outer->NumDirectMethods());
+
+  Class* inner = class_linker_->FindClass("LNested$Inner;", class_loader);
+  ASSERT_TRUE(inner != NULL);
+  EXPECT_EQ(0U, inner->NumVirtualMethods());
+  EXPECT_EQ(1U, inner->NumDirectMethods());
+}
+
+TEST_F(ClassLinkerTest, FindClass_Primitives) {
+  StringPiece expected = "BCDFIJSZV";
+  for (int ch = 0; ch < 255; ch++) {
+    char* s = reinterpret_cast<char*>(&ch);
+    StringPiece descriptor(s, 1);
+    if (expected.find(ch) == StringPiece::npos) {
+      AssertNonExistentClass(descriptor);
+    } else {
+      AssertPrimitiveClass(descriptor);
+    }
+  }
+}
+
+TEST_F(ClassLinkerTest, FindClass) {
+  Class* JavaLangObject = class_linker_->FindSystemClass("Ljava/lang/Object;");
+  ASSERT_TRUE(JavaLangObject != NULL);
+  ASSERT_TRUE(JavaLangObject->GetClass() != NULL);
+  ASSERT_EQ(JavaLangObject->GetClass(), JavaLangObject->GetClass()->GetClass());
+  EXPECT_EQ(JavaLangObject, JavaLangObject->GetClass()->GetSuperClass());
+  ASSERT_TRUE(JavaLangObject->GetDescriptor()->Equals("Ljava/lang/Object;"));
+  EXPECT_TRUE(JavaLangObject->GetSuperClass() == NULL);
+  EXPECT_FALSE(JavaLangObject->HasSuperClass());
+  EXPECT_TRUE(JavaLangObject->GetClassLoader() == NULL);
+  EXPECT_FALSE(JavaLangObject->IsErroneous());
+  EXPECT_TRUE(JavaLangObject->IsVerified());
+  EXPECT_TRUE(JavaLangObject->IsResolved());
+  EXPECT_FALSE(JavaLangObject->IsArrayInstance());
+  EXPECT_FALSE(JavaLangObject->IsArrayClass());
+  EXPECT_TRUE(JavaLangObject->GetComponentType() == NULL);
+  EXPECT_FALSE(JavaLangObject->IsInterface());
+  EXPECT_TRUE(JavaLangObject->IsPublic());
+  EXPECT_FALSE(JavaLangObject->IsFinal());
+  EXPECT_FALSE(JavaLangObject->IsPrimitive());
+  EXPECT_FALSE(JavaLangObject->IsSynthetic());
+  EXPECT_EQ(2U, JavaLangObject->NumDirectMethods());
+  EXPECT_EQ(11U, JavaLangObject->NumVirtualMethods());
+  EXPECT_EQ(2U, JavaLangObject->NumInstanceFields());
+  EXPECT_TRUE(JavaLangObject->GetInstanceField(0)->GetName()->Equals("shadow$_klass_"));
+  EXPECT_TRUE(JavaLangObject->GetInstanceField(1)->GetName()->Equals("shadow$_monitor_"));
+
+  EXPECT_EQ(0U, JavaLangObject->NumStaticFields());
+  EXPECT_EQ(0U, JavaLangObject->NumInterfaces());
+
+  const ClassLoader* class_loader = LoadDex("MyClass");
+  AssertNonExistentClass("LMyClass;");
+  Class* MyClass = class_linker_->FindClass("LMyClass;", class_loader);
+  ASSERT_TRUE(MyClass != NULL);
+  ASSERT_TRUE(MyClass->GetClass() != NULL);
+  ASSERT_EQ(MyClass->GetClass(), MyClass->GetClass()->GetClass());
+  EXPECT_EQ(JavaLangObject, MyClass->GetClass()->GetSuperClass());
+  ASSERT_TRUE(MyClass->GetDescriptor()->Equals("LMyClass;"));
+  EXPECT_TRUE(MyClass->GetSuperClass() == JavaLangObject);
+  EXPECT_TRUE(MyClass->HasSuperClass());
+  EXPECT_EQ(class_loader, MyClass->GetClassLoader());
+  EXPECT_TRUE(MyClass->GetStatus() == Class::kStatusResolved);
+  EXPECT_FALSE(MyClass->IsErroneous());
+  EXPECT_FALSE(MyClass->IsVerified());
+  EXPECT_TRUE(MyClass->IsResolved());
+  EXPECT_FALSE(MyClass->IsArrayInstance());
+  EXPECT_FALSE(MyClass->IsArrayClass());
+  EXPECT_TRUE(MyClass->GetComponentType() == NULL);
+  EXPECT_FALSE(MyClass->IsInterface());
+  EXPECT_FALSE(MyClass->IsPublic());
+  EXPECT_FALSE(MyClass->IsFinal());
+  EXPECT_FALSE(MyClass->IsPrimitive());
+  EXPECT_FALSE(MyClass->IsSynthetic());
+  EXPECT_EQ(1U, MyClass->NumDirectMethods());
+  EXPECT_EQ(0U, MyClass->NumVirtualMethods());
+  EXPECT_EQ(0U, MyClass->NumInstanceFields());
+  EXPECT_EQ(0U, MyClass->NumStaticFields());
+  EXPECT_EQ(0U, MyClass->NumInterfaces());
+
+  EXPECT_EQ(JavaLangObject->GetClass()->GetClass(), MyClass->GetClass()->GetClass());
+
+  // created by class_linker
+  AssertArrayClass("[C", "C", NULL);
+  AssertArrayClass("[Ljava/lang/Object;", "Ljava/lang/Object;", NULL);
+  // synthesized on the fly
+  AssertArrayClass("[[C", "[C", NULL);
+  AssertArrayClass("[[[LMyClass;", "[[LMyClass;", class_loader);
+  // or not available at all
+  AssertNonExistentClass("[[[[LNonExistentClass;");
+}
+
+TEST_F(ClassLinkerTest, LibCore) {
+  AssertDexFile(java_lang_dex_file_.get(), NULL);
+}
+
 // The first reference array element must be a multiple of 8 bytes from the
 // start of the object
 TEST_F(ClassLinkerTest, ValidateObjectArrayElementsOffset) {
diff --git a/src/dex_file.cc b/src/dex_file.cc
index 10ffab3..c17a225 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -435,7 +435,7 @@
 }
 
 const DexFile::ClassDef* DexFile::FindClassDef(const StringPiece& descriptor) const {
-  CHECK(descriptor != NULL);
+  CHECK(!descriptor.empty());
   Index::const_iterator it = index_.find(descriptor);
   if (it == index_.end()) {
     return NULL;
diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc
index b15e7bd..e0032b2 100644
--- a/src/dex_verifier.cc
+++ b/src/dex_verifier.cc
@@ -505,7 +505,7 @@
   const uint16_t* array_data;
   int32_t array_data_offset;
 
-  assert(cur_offset < insn_count);
+  DCHECK_LT(cur_offset, insn_count);
 
   /* make sure the start of the array data table is in range */
   array_data_offset = insns[1] | (((int32_t) insns[2]) << 16);
@@ -839,7 +839,7 @@
   reg_table->insn_reg_count_plus_ = registers_size + kExtraRegs;
   reg_table->register_lines_.reset(new RegisterLine[insns_size]());
 
-  assert(insns_size > 0);
+  DCHECK_GT(insns_size, 0U);
 
   bool track_monitors;
   //if (gDvm.monitorVerification) {
@@ -929,7 +929,7 @@
     inst = inst->Next();
   }
 
-  assert(idx == new_instance_count);
+  CHECK_EQ(idx, new_instance_count);
   return uninit_map;
 }
 
@@ -966,7 +966,7 @@
     }
 
     /* Check if the descriptor is an array. */
-    if (descriptor[0] == '[') {
+    if (descriptor[0] == '[' && descriptor[1] != '\0') {
       /*
        * There should never be a problem loading primitive arrays.
        */
@@ -1012,7 +1012,7 @@
 
 Class* DexVerifier::LookupSignatureClass(const Method* method, std::string sig,
     VerifyError* failure) {
-  assert(sig[0] == 'L');
+  DCHECK_EQ(sig[0], 'L');
   size_t end = sig.find(';');
 
   if (end == std::string::npos) {
@@ -1027,7 +1027,7 @@
 
 Class* DexVerifier::LookupSignatureArrayClass(const Method* method,
     std::string sig, VerifyError* failure) {
-  assert(sig[0] == '[');
+  DCHECK_EQ(sig[0], '[');
   size_t end = 0;
 
   while (sig[end] == '[')
@@ -1058,7 +1058,7 @@
   int expected_args = code_item->ins_size_;   /* long/double count as two */
   int actual_args = 0;
 
-  assert(arg_start >= 0);      /* should have been verified earlier */
+  DCHECK_GE(arg_start, 0);      /* should have been verified earlier */
 
   /*
    * Include the "this" pointer.
@@ -1074,7 +1074,7 @@
     if (IsInitMethod(method) && method->GetDeclaringClass() != klass_object) {
       int idx = SetUninitInstance(uninit_map, kUninitThisArgAddr,
           method->GetDeclaringClass());
-      assert(idx == 0);
+      DCHECK_EQ(idx, 0);
       reg_types[arg_start + actual_args] = RegTypeFromUninitIndex(idx);
     } else {
       reg_types[arg_start + actual_args] =
@@ -1218,7 +1218,7 @@
 int DexVerifier::SetUninitInstance(UninitInstanceMap* uninit_map, int addr,
     Class* klass) {
   int idx;
-  assert(klass != NULL);
+  DCHECK(klass != NULL);
 
   /* TODO: binary search when num_entries > 8 */
   for (idx = uninit_map->num_entries_ - 1; idx >= 0; idx--) {
@@ -1235,8 +1235,7 @@
     }
   }
 
-  LOG(ERROR) << "VFY: addr " << addr << " not found in uninit map";
-  assert(false);      // shouldn't happen
+  LOG(FATAL) << "VFY: addr " << addr << " not found in uninit map";
   return -1;
 }
 
@@ -1508,7 +1507,7 @@
        */
       res_class = GetCaughtExceptionType(vdata, insn_idx, &failure);
       if (res_class == NULL) {
-        assert(failure != VERIFY_ERROR_NONE);
+        DCHECK(failure != VERIFY_ERROR_NONE);
       } else {
         SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(res_class));
       }
@@ -1583,8 +1582,8 @@
         }
 
         /* return_type is the *expected* return type, not register value */
-        assert(return_type != kRegTypeZero);
-        assert(!RegTypeIsUninitReference(return_type));
+        DCHECK(return_type != kRegTypeZero);
+        DCHECK(!RegTypeIsUninitReference(return_type));
 
         /*
          * Verify that the reference in vAA is an instance of the type
@@ -1649,7 +1648,7 @@
         LOG(ERROR) << "VFY: unable to resolve const-class " << dec_insn.vB_
                    << " (" << bad_class_desc << ") in "
                    << klass->GetDescriptor()->ToModifiedUtf8();
-        assert(failure != VERIFY_ERROR_GENERIC);
+        DCHECK(failure != VERIFY_ERROR_GENERIC);
       } else {
         SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(
             class_linker->FindSystemClass("Ljava/lang/Class;")));
@@ -1700,7 +1699,7 @@
         LOG(ERROR) << "VFY: unable to resolve check-cast " << dec_insn.vB_
                    << " (" << bad_class_desc << ") in "
                    << klass->GetDescriptor()->ToModifiedUtf8();
-        assert(failure != VERIFY_ERROR_GENERIC);
+        DCHECK(failure != VERIFY_ERROR_GENERIC);
       } else {
         RegType orig_type;
 
@@ -1729,7 +1728,7 @@
         LOG(ERROR) << "VFY: unable to resolve instanceof " << dec_insn.vC_
                    << " (" << bad_class_desc << ") in "
                    << klass->GetDescriptor()->ToModifiedUtf8();
-        assert(failure != VERIFY_ERROR_GENERIC);
+        DCHECK(failure != VERIFY_ERROR_GENERIC);
       } else {
         /* result is boolean */
         SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
@@ -1755,7 +1754,7 @@
         LOG(ERROR) << "VFY: unable to resolve new-instance " << dec_insn.vB_
                    << " (" << bad_class_desc << ") in "
                    << klass->GetDescriptor()->ToModifiedUtf8();
-        assert(failure != VERIFY_ERROR_GENERIC);
+        DCHECK(failure != VERIFY_ERROR_GENERIC);
       } else {
         RegType uninit_type;
 
@@ -1769,7 +1768,7 @@
 
         /* add resolved class to uninit map if not already there */
         int uidx = SetUninitInstance(uninit_map, insn_idx, res_class);
-        assert(uidx >= 0);
+        DCHECK_GE(uidx, 0);
         uninit_type = RegTypeFromUninitIndex(uidx);
 
         /*
@@ -1790,7 +1789,7 @@
         LOG(ERROR) << "VFY: unable to resolve new-array " << dec_insn.vC_
                    << " (" << bad_class_desc << ") in "
                    << klass->GetDescriptor()->ToModifiedUtf8();
-        assert(failure != VERIFY_ERROR_GENERIC);
+        DCHECK(failure != VERIFY_ERROR_GENERIC);
       } else if (!res_class->IsArrayClass()) {
         LOG(ERROR) << "VFY: new-array on non-array class";
         failure = VERIFY_ERROR_GENERIC;
@@ -1809,7 +1808,7 @@
         LOG(ERROR) << "VFY: unable to resolve filled-array " << dec_insn.vB_
                    << " (" << bad_class_desc << ") in "
                    << klass->GetDescriptor()->ToModifiedUtf8();
-        assert(failure != VERIFY_ERROR_GENERIC);
+        DCHECK(failure != VERIFY_ERROR_GENERIC);
       } else if (!res_class->IsArrayClass()) {
         LOG(ERROR) << "VFY: filled-new-array on non-array class";
         failure = VERIFY_ERROR_GENERIC;
@@ -1888,7 +1887,7 @@
 
         Class::PrimitiveType prim_type =
             res_class->GetComponentType()->GetPrimitiveType();
-        if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
+        if (!res_class->IsArrayClass() ||
             prim_type == Class::kPrimNot || prim_type == Class::kPrimVoid) {
           LOG(ERROR) << "VFY: invalid fill-array-data on " <<
                 res_class->GetDescriptor()->ToModifiedUtf8();
@@ -1897,7 +1896,7 @@
         }
 
         value_type = PrimitiveTypeToRegType(prim_type);
-        assert(value_type != kRegTypeUnknown);
+        DCHECK(value_type != kRegTypeUnknown);
 
         /*
          * Now verify if the element width in the table matches the element
@@ -2033,8 +2032,7 @@
           /* verify the class */
           Class::PrimitiveType prim_type =
               res_class->GetComponentType()->GetPrimitiveType();
-          if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
-              prim_type == Class::kPrimNot) {
+          if (!res_class->IsArrayClass() || prim_type == Class::kPrimNot) {
             LOG(ERROR) << "VFY: invalid aget-1nr target "
                        << res_class->GetDescriptor()->ToModifiedUtf8();
             failure = VERIFY_ERROR_GENERIC;
@@ -2077,8 +2075,7 @@
           /* verify the class */
           Class::PrimitiveType prim_type =
               res_class->GetComponentType()->GetPrimitiveType();
-          if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
-              prim_type == Class::kPrimNot) {
+          if (!res_class->IsArrayClass() || prim_type == Class::kPrimNot) {
             LOG(ERROR) << "VFY: invalid aget-wide target "
                        << res_class->GetDescriptor()->ToModifiedUtf8();
             failure = VERIFY_ERROR_GENERIC;
@@ -2127,29 +2124,19 @@
         if (res_class != NULL) {
           Class* element_class;
 
-          assert(res_class != NULL);
+          DCHECK(res_class != NULL);
           if (!res_class->IsArrayClass()) {
             LOG(ERROR) << "VFY: aget-object on non-array class";
             failure = VERIFY_ERROR_GENERIC;
             break;
           }
-          assert(res_class->GetComponentType() != NULL);
+          DCHECK(res_class->GetComponentType() != NULL);
 
           /*
-           * Find the element class. res_class->GetComponentType() indicates
-           * the basic type, which won't be what we want for a
-           * multi-dimensional array.
+           * Find the element class.
            */
-          if (res_class->GetDescriptor()->CharAt(1) == '[') {
-            assert(res_class->GetArrayRank() > 1);
-            std::string descriptor =
-                res_class->GetDescriptor()->ToModifiedUtf8();
-            element_class = class_linker->FindClass(descriptor.c_str() + 1,
-                           res_class->GetClassLoader());
-          } else if (res_class->GetDescriptor()->CharAt(1) == 'L') {
-            assert(res_class->GetArrayRank() == 1);
-            element_class = res_class->GetComponentType();
-          } else {
+          element_class = res_class->GetComponentType();
+          if (element_class->IsPrimitive()) {
             LOG(ERROR) << "VFY: aget-object on non-ref array class ("
                        << res_class->GetDescriptor()->ToModifiedUtf8() << ")";
             failure = VERIFY_ERROR_GENERIC;
@@ -2204,8 +2191,7 @@
 
         Class::PrimitiveType prim_type =
             res_class->GetComponentType()->GetPrimitiveType();
-        if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
-            prim_type == Class::kPrimNot) {
+        if (!res_class->IsArrayClass() || prim_type == Class::kPrimNot) {
           LOG(ERROR) << "VFY: invalid aput-1nr on "
                      << res_class->GetDescriptor()->ToModifiedUtf8();
           failure = VERIFY_ERROR_GENERIC;
@@ -2253,8 +2239,7 @@
         Class::PrimitiveType prim_type =
             res_class->GetComponentType()->GetPrimitiveType();
         /* verify the class and try to refine "dst_type" */
-        if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
-            prim_type == Class::kPrimNot)
+        if (!res_class->IsArrayClass() || prim_type == Class::kPrimNot)
         {
           LOG(ERROR) << "VFY: invalid aput-wide on "
                      << res_class->GetDescriptor()->ToModifiedUtf8();
@@ -2310,26 +2295,15 @@
           }
 
           /*
-           * Find the element class. res_class->GetComponentType() indicates
-           * the basic type, which won't be what we want for a
-           * multi-dimensional array.
+           * Find the element class.
            *
            * All we want to check here is that the element type is a
            * reference class. We *don't* check instanceof here, because
            * you can still put a String into a String[] after the latter
            * has been cast to an Object[].
            */
-          if (array_class->GetDescriptor()->CharAt(1) == '[') {
-            assert(array_class->GetArrayRank() > 1);
-            std::string descriptor =
-                array_class->GetDescriptor()->ToModifiedUtf8();
-            element_class = class_linker->FindClass(descriptor.c_str() + 1,
-                           array_class->GetClassLoader());
-          } else {
-            assert(array_class->GetArrayRank() == 1);
-            element_class = array_class->GetComponentType();
-          }
-          if (element_class->GetPrimitiveType() != Class::kPrimNot) {
+          element_class = array_class->GetComponentType();
+          if (element_class->IsPrimitive()) {
             LOG(ERROR) << "VFY: invalid aput-object of "
                        << res_class->GetDescriptor()->ToModifiedUtf8()
                        << " into "
@@ -2438,7 +2412,7 @@
           break;
         }
         if (failure == VERIFY_ERROR_NONE) {
-          assert(!field_class->IsPrimitive());
+          DCHECK(!field_class->IsPrimitive()) << PrettyClass(field_class);
           SetRegisterType(work_line, dec_insn.vA_,
               RegTypeFromClass(field_class));
         }
@@ -2925,7 +2899,7 @@
           Class* this_class;
 
           this_class = RegTypeReferenceToClass(this_type, uninit_map);
-          assert(this_class != NULL);
+          DCHECK(this_class != NULL);
 
           /* must be in same class or in superclass */
           if (called_method->GetDeclaringClass() == this_class->GetSuperClass())
@@ -3492,8 +3466,7 @@
       LOG(ERROR) << "VFY: bad branch at 0x" << std::hex << insn_idx << std::dec;
       return false;
     }
-    assert(isConditional || (opcode_flag & Instruction::kContinue) == 0);
-    assert(!isConditional || (opcode_flag & Instruction::kContinue) != 0);
+    DCHECK_EQ(isConditional, (opcode_flag & Instruction::kContinue) != 0);
 
     if (!CheckMoveException(code_item->insns_, insn_idx + branch_target))
       return false;
@@ -3521,7 +3494,7 @@
       offset_to_targets = 4;
     } else {
       /* 0 = sig, 1 = count, 2..count * 2 = keys */
-      assert((*insns & 0xff) == Instruction::SPARSE_SWITCH);
+      DCHECK((*insns & 0xff) == Instruction::SPARSE_SWITCH);
       offset_to_targets = 2 + 2 * switch_count;
     }
 
@@ -3535,7 +3508,7 @@
          (((int32_t) switch_insns[offset_to_targets + targ * 2 + 1]) << 16);
       abs_offset = insn_idx + offset;
 
-      assert(abs_offset < insns_size);
+      DCHECK_LT(abs_offset, insns_size);
 
       if (!CheckMoveException(code_item->insns_, abs_offset))
         return false;
@@ -3615,8 +3588,8 @@
     *start_guess = insn_idx + branch_target;
   }
 
-  assert(*start_guess < insns_size &&
-      InsnGetWidth(insn_flags, *start_guess) != 0);
+  DCHECK_LT(*start_guess, insns_size);
+  DCHECK(InsnGetWidth(insn_flags, *start_guess) != 0);
 
   return true;
 }
@@ -3696,7 +3669,7 @@
       return false;
   }
 
-  assert(inst->IsThrow());
+  DCHECK(inst->IsThrow());
 
   /* write a NOP over the third code unit, if necessary */
   int width = InsnGetWidth(insn_flags, insn_idx);
@@ -3716,7 +3689,7 @@
 
   /* encode the opcode, with the failure code in the high byte */
   // TODO: REPLACE FAILING OPCODES
-  //assert(width == 2 || width == 3);
+  //DCHECK(width == 2 || width == 3);
   //uint16_t new_val = Instruction::THROW_VERIFICATION_ERROR |
   //uint16_t new_val = Instruction::UNUSED_ED |
       //(failure << 8) | (ref_type << (8 + kVerifyErrorRefTypeShift));
@@ -3835,7 +3808,7 @@
    * declared by this class.
    */
   obj_class = RegTypeReferenceToClass(obj_type, uninit_map);
-  assert(obj_class != NULL);
+  DCHECK(obj_class != NULL);
   if (RegTypeIsUninitReference(obj_type)) {
     if (!IsInitMethod(method) || method->GetDeclaringClass() != obj_class) {
       LOG(ERROR) << "VFY: attempt to access field via uninitialized ref";
@@ -4135,15 +4108,14 @@
     case kRegTypeUnknown:
     case kRegTypeConflict:
       /* should never be checking for these explicitly */
-      assert(false);
+      DCHECK(false);
       *failure = VERIFY_ERROR_GENERIC;
       return;
     case kRegTypeUninit:
     default:
       /* make sure check_type is initialized reference */
       if (!RegTypeIsReference(check_type)) {
-        LOG(ERROR) << "VFY: unexpected check type " << check_type;
-        assert(false);
+        LOG(FATAL) << "VFY: unexpected check type " << check_type;
         *failure = VERIFY_ERROR_GENERIC;
         break;
       }
@@ -4168,8 +4140,8 @@
       if (src_type != kRegTypeZero) {
         Class* src_class = RegTypeInitializedReferenceToClass(src_type);
         Class* check_class = RegTypeInitializedReferenceToClass(check_type);
-        assert(src_class != NULL);
-        assert(check_class != NULL);
+        DCHECK(src_class != NULL);
+        DCHECK(check_class != NULL);
 
         if (!check_class->IsAssignableFrom(src_class)) {
           LOG(ERROR) << "VFY: " << src_class->GetDescriptor()->ToModifiedUtf8()
@@ -4210,7 +4182,7 @@
       changed++;
     }
   }
-  assert(changed > 0);
+  DCHECK_GT(changed, 0);
 
   return;
 }
@@ -4230,7 +4202,7 @@
 
 void DexVerifier::CopyRegister1(RegisterLine* register_line, uint32_t vdst,
     uint32_t vsrc, TypeCategory cat, VerifyError* failure) {
-  assert(cat == kTypeCategory1nr || cat == kTypeCategoryRef);
+  DCHECK(cat == kTypeCategory1nr || cat == kTypeCategoryRef);
   RegType type = GetRegisterType(register_line, vsrc);
   CheckTypeCategory(type, cat, failure);
   if (*failure != VERIFY_ERROR_NONE) {
@@ -4263,7 +4235,7 @@
 void DexVerifier::CopyResultRegister1(RegisterLine* register_line,
     const int insn_reg_count, uint32_t vdst, TypeCategory cat,
     VerifyError* failure) {
-  assert(vdst < (uint32_t) insn_reg_count);
+  DCHECK_LT(vdst, static_cast<uint32_t>(insn_reg_count));
 
   uint32_t vsrc = RESULT_REGISTER(insn_reg_count);
   RegType type = GetRegisterType(register_line, vsrc);
@@ -4283,7 +4255,7 @@
  */
 void DexVerifier::CopyResultRegister2(RegisterLine* register_line,
     const int insn_reg_count, uint32_t vdst, VerifyError* failure) {
-  assert(vdst < (uint32_t) insn_reg_count);
+  DCHECK_LT(vdst, static_cast<uint32_t>(insn_reg_count));
 
   uint32_t vsrc = RESULT_REGISTER(insn_reg_count);
   RegType type_l = GetRegisterType(register_line, vsrc);
@@ -4332,77 +4304,33 @@
   while (c1 != c2) {
     c1 = c1->GetSuperClass();
     c2 = c2->GetSuperClass();
-
-    assert(c1 != NULL && c2 != NULL);
+    DCHECK(c1 != NULL);
+    DCHECK(c2 != NULL);
   }
 
   return c1;
 }
 
 Class* DexVerifier::FindCommonArraySuperclass(Class* c1, Class* c2) {
-  Class* array_class = NULL;
-  Class* common_elem;
-  int array_dim1, array_dim2;
-  int i, num_dims;
-  bool has_primitive = false;
-
-  array_dim1 = c1->GetArrayRank();
-  array_dim2 = c2->GetArrayRank();
-  assert(c1->GetArrayRank() > 0);
-  assert(c2->GetArrayRank() > 0);
-
-  if (c1->GetComponentType()->IsPrimitive()) {
-    array_dim1--;
-    has_primitive = true;
+  DCHECK(c1->IsArrayClass());
+  DCHECK(c2->IsArrayClass());
+  Class* e1 = c1->GetComponentType();
+  Class* e2 = c2->GetComponentType();
+  if (e1->IsPrimitive() || e2->IsPrimitive()) {
+    return c1->GetSuperClass();  // == java.lang.Object
   }
-  if (c2->GetComponentType()->IsPrimitive()) {
-    array_dim2--;
-    has_primitive = true;
-  }
-
-  if (!has_primitive && array_dim1 == array_dim2) {
-    /*
-     * Two arrays of reference types with equal dimensions. Try to
-     * find a good match.
-     */
-    common_elem = FindCommonSuperclass(c1->GetComponentType(),
-        c2->GetComponentType());
-    num_dims = array_dim1;
-  } else {
-    /*
-     * Mismatched array depths and/or array(s) of primitives. We want
-     * Object, or an Object array with appropriate dimensions.
-     *
-     * We initialize array_class to Object here, because it's possible
-     * for us to set num_dims=0.
-     */
-    if (array_dim1 < array_dim2)
-      num_dims = array_dim1;
-    else
-      num_dims = array_dim2;
-    array_class = common_elem = c1->GetSuperClass();  // == java.lang.Object
-  }
-
-  /*
-   * Find an appropriately-dimensioned array class. This is easiest
-   * to do iteratively, using the array class found by the current round
-   * as the element type for the next round.
-   */
-  for (i = 0; i < num_dims; i++) {
-    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-    const ClassLoader* class_loader = c1->GetClassLoader();
-    std::string descriptor = "[" +
-        common_elem->GetDescriptor()->ToModifiedUtf8();
-    array_class = class_linker->FindClass(descriptor.c_str(), class_loader);
-    common_elem = array_class;
-  }
-  assert(array_class != NULL);
-
+  Class* common_elem = FindCommonSuperclass(c1->GetComponentType(), c2->GetComponentType());
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  const ClassLoader* class_loader = c1->GetClassLoader();
+  std::string descriptor = "[" + common_elem->GetDescriptor()->ToModifiedUtf8();
+  Class* array_class = class_linker->FindClass(descriptor.c_str(), class_loader);
+  DCHECK(array_class != NULL);
   return array_class;
 }
 
 Class* DexVerifier::FindCommonSuperclass(Class* c1, Class* c2) {
-  assert(!c1->IsPrimitive() && !c2->IsPrimitive());
+  DCHECK(!c1->IsPrimitive()) << PrettyClass(c1);
+  DCHECK(!c2->IsPrimitive()) << PrettyClass(c2);
 
   if (c1 == c2)
     return c1;
@@ -4487,7 +4415,7 @@
         Class* klass1 = RegTypeInitializedReferenceToClass(type1);
         Class* klass2 = RegTypeInitializedReferenceToClass(type2);
         Class* merged_class = FindCommonSuperclass(klass1, klass2);
-        assert(merged_class != NULL);
+        DCHECK(merged_class != NULL);
         result = RegTypeFromClass(merged_class);
       }
     }
@@ -4509,7 +4437,7 @@
 bool DexVerifier::UpdateRegisters(InsnFlags* insn_flags,
     RegisterTable* reg_table, int next_insn, const RegisterLine* work_line) {
   const size_t insn_reg_count_plus = reg_table->insn_reg_count_plus_;
-  assert(work_line != NULL);
+  DCHECK(work_line != NULL);
   const RegType* work_regs = work_line->reg_types_.get();
 
   if (!InsnIsVisitedOrChanged(insn_flags, next_insn)) {
@@ -4531,7 +4459,7 @@
     bool changed = false;
     unsigned int idx;
 
-    assert(target_regs != NULL);
+    DCHECK(target_regs != NULL);
     if (target_mon_ents != NULL) {
       /* Monitor stacks must be identical. */
       if (target_line->monitor_stack_top_ != work_line->monitor_stack_top_) {
@@ -4589,7 +4517,8 @@
     { /*F*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
   };
 
-  assert(check_type >= kRegType1nrSTART && check_type <= kRegType1nrEND);
+  DCHECK(check_type >= kRegType1nrSTART);
+  DCHECK(check_type <= kRegType1nrEND);
 
   if (src_type >= kRegType1nrSTART && src_type <= kRegType1nrEND)
     return (bool) conv_tab[src_type - kRegType1nrSTART]
@@ -4755,7 +4684,7 @@
         *failure = VERIFY_ERROR_GENERIC;
       break;
     default:
-      assert(false);
+      DCHECK(false);
       *failure = VERIFY_ERROR_GENERIC;
       break;
   }
@@ -4794,7 +4723,7 @@
   VerifyRegisterType(register_line, dec_insn->vB_, src_type, failure);
 
   if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
-    assert(dst_type == kRegTypeInteger);
+    DCHECK(dst_type == kRegTypeInteger);
 
     /* check vB with the call, then check the constant manually */
     if (UpcastBooleanOp(register_line, dec_insn->vB_, dec_insn->vB_)
@@ -4814,7 +4743,7 @@
   VerifyRegisterType(register_line, dec_insn->vC_, src_type2, failure);
 
   if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
-    assert(dst_type == kRegTypeInteger);
+    DCHECK(dst_type == kRegTypeInteger);
     if (UpcastBooleanOp(register_line, dec_insn->vB_, dec_insn->vC_))
       dst_type = kRegTypeBoolean;
   }
@@ -4830,7 +4759,7 @@
   VerifyRegisterType(register_line, dec_insn->vB_, src_type2, failure);
 
   if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
-    assert(dst_type == kRegTypeInteger);
+    DCHECK(dst_type == kRegTypeInteger);
     if (UpcastBooleanOp(register_line, dec_insn->vA_, dec_insn->vB_))
       dst_type = kRegTypeBoolean;
   }
@@ -4908,7 +4837,7 @@
       break;
     default:
       /* long, double, references; shouldn't be here! */
-      assert(false);
+      DCHECK(false);
       break;
   }
 
@@ -4924,7 +4853,7 @@
   Class::PrimitiveType elem_type;
   unsigned int ui;
 
-  assert(res_class->IsArrayClass());
+  DCHECK(res_class->IsArrayClass()) << PrettyClass(res_class);
   elem_type = res_class->GetComponentType()->GetPrimitiveType();
   if (elem_type == Class::kPrimNot) {
     expected_type = RegTypeFromClass(res_class->GetComponentType());
@@ -5039,7 +4968,7 @@
    * method's class' superclass has a vtable entry for the target method.
    */
   if (is_super) {
-    assert(method_type == METHOD_VIRTUAL);
+    DCHECK(method_type == METHOD_VIRTUAL);
     Class* super = method->GetDeclaringClass()->GetSuperClass();
     if (super == NULL || res_method->GetMethodIndex() > super->GetVTable()->GetLength()) {
       if (super == NULL) {
@@ -5071,7 +5000,7 @@
   actual_args = 0;
 
   /* caught by static verifier */
-  assert(is_range || expected_args <= 5);
+  DCHECK(is_range || expected_args <= 5);
 
   if (expected_args > code_item->outs_size_) {
     LOG(ERROR) << "VFY: invalid arg count (" << expected_args
@@ -5300,7 +5229,7 @@
   uint8_t* map_data = map->data_;
   for (i = 0; i < (int) vdata->code_item_->insns_size_; i++) {
     if (InsnIsGcPoint(vdata->insn_flags_.get(), i)) {
-      assert(vdata->register_lines_[i].reg_types_.get() != NULL);
+      DCHECK(vdata->register_lines_[i].reg_types_.get() != NULL);
       if (format == kRegMapFormatCompact8) {
         *map_data++ = i;
       } else /*kRegMapFormatCompact16*/ {
@@ -5313,7 +5242,7 @@
     }
   }
 
-  assert((uint32_t) map_data - (uint32_t) map->data_ == data_size);
+  DCHECK_EQ((uint32_t) map_data - (uint32_t) map->data_, data_size);
 
   // TODO: Remove this check when it's really running...
 #if 1
@@ -5410,7 +5339,7 @@
   uint8_t format = map->header_->format_;
   uint16_t num_entries = map->header_->num_entries_;
 
-  assert(num_entries > 0);
+  DCHECK_GT(num_entries, 0);
 
   switch (format) {
     case kRegMapFormatNone:
@@ -5447,7 +5376,7 @@
 
       data += line_width;
     }
-    assert(data == map->data_ + line_width * num_entries);
+    DCHECK_EQ(data, map->data_ + line_width * num_entries);
   } else {
     int hi, lo, mid;
 
@@ -5588,7 +5517,7 @@
   uint8_t format = map->header_->format_;
   uint16_t num_entries = map->header_->num_entries_;
 
-  assert(map != NULL);
+  DCHECK(map != NULL);
 
   switch (format) {
     case kRegMapFormatNone:
@@ -5647,13 +5576,17 @@
     }
   }
 
-  if (num_bits_changed > 0)
-    assert(first_bit_changed >= 0);
+  if (num_bits_changed > 0) {
+    DCHECK_GE(first_bit_changed, 0);
+  }
 
-  if (first_bit_changed_ptr != NULL)
+  if (first_bit_changed_ptr != NULL) {
     *first_bit_changed_ptr = first_bit_changed;
-  if (num_bits_changed_ptr != NULL)
+  }
+
+  if (num_bits_changed_ptr != NULL) {
     *num_bits_changed_ptr = num_bits_changed;
+  }
 
   return leb_size;
 }
@@ -5744,7 +5677,7 @@
       addr |= (*map_data++) << 8;
 
     addr_diff = addr - prev_addr;
-    assert(addr_diff > 0);
+    DCHECK_GT(addr_diff, 0);
     if (addr_diff < 8) {
       /* Small difference, encode in 3 bits. */
       key = addr_diff -1;          /* set 00000AAA */
diff --git a/src/java_lang_Class.cc b/src/java_lang_Class.cc
index 0c6bbe5..3e80c6b 100644
--- a/src/java_lang_Class.cc
+++ b/src/java_lang_Class.cc
@@ -35,24 +35,7 @@
 }
 
 jclass Class_getComponentType(JNIEnv* env, jobject javaThis) {
-  Class* c = Decode<Class*>(env, javaThis);
-  if (!c->IsArrayClass()) {
-      return NULL;
-  }
-
-  /*
-   * We can't just return c->GetComponentType(), because that gives
-   * us the base type (e.g. X[][][] returns X).  If this is a multi-
-   * dimensional array, we have to do the lookup by name.
-   */
-  Class* result;
-  std::string descriptor(c->GetDescriptor()->ToModifiedUtf8());
-  if (descriptor[1] == '[') {
-    result = Runtime::Current()->GetClassLinker()->FindClass(descriptor.c_str() + 1, c->GetClassLoader());
-  } else {
-    result = c->GetComponentType();
-  }
-  return AddLocalReference<jclass>(env, result);
+  return AddLocalReference<jclass>(env, Decode<Class*>(env, javaThis)->GetComponentType());
 }
 
 jobjectArray Class_getDeclaredClasses(JNIEnv* env, jclass java_lang_Class_class, jclass c, jboolean publicOnly) {
diff --git a/src/java_lang_System.cc b/src/java_lang_System.cc
index fc13839..4eaaa66 100644
--- a/src/java_lang_System.cc
+++ b/src/java_lang_System.cc
@@ -182,10 +182,10 @@
   }
 
   // Neither class is primitive. Are the types trivially compatible?
-  const int width = sizeof(Object*);
-  bool sameDimensions = srcArray->GetClass()->GetArrayRank() == dstArray->GetClass()->GetArrayRank();
-  if (sameDimensions && srcComponentType->InstanceOf(dstComponentType)) {
+  const size_t width = sizeof(Object*);
+  if (dstComponentType->IsAssignableFrom(srcComponentType)) {
     // Yes. Bulk copy.
+    DCHECK_EQ(width, sizeof(uint32_t));
     move32(dstBytes + dstPos * width, srcBytes + srcPos * width, length * width);
     Heap::WriteBarrier(dstArray);
     return;
diff --git a/src/java_lang_reflect_Array.cc b/src/java_lang_reflect_Array.cc
new file mode 100644
index 0000000..b1ae682
--- /dev/null
+++ b/src/java_lang_reflect_Array.cc
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "jni_internal.h"
+#include "class_linker.h"
+#include "object.h"
+
+#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
+
+namespace art {
+
+namespace {
+
+
+// Recursively create an array with multiple dimensions.  Elements may be
+// Objects or primitive types.
+//
+// The dimension we're creating is in dimensions[0], so when we recurse
+// we advance the pointer.
+Array* CreateMultiArray(Class* array_class, int current_dimension, IntArray* dimensions) {
+  int32_t array_length = dimensions->Get(current_dimension++);
+  Array* new_array = Array::Alloc(array_class, array_length);
+  if (new_array == NULL) {
+    CHECK(Thread::Current()->IsExceptionPending());
+    return NULL;
+  }
+  if (current_dimension == dimensions->GetLength()) {
+    return new_array;
+  }
+
+  if (!array_class->GetComponentType()->IsArrayClass()) {
+    // TODO: throw an exception, not relying on class_linker->FindClass to throw.
+    // old code assumed this but if you recurse from "[Foo" to "Foo" to "oo",
+    // you shouldn't assume there isn't a class "oo".
+  }
+  std::string sub_array_descriptor(array_class->GetDescriptor()->ToModifiedUtf8(), 1);
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  Class* sub_array_class = class_linker->FindClass(sub_array_descriptor,
+                                                   array_class->GetClassLoader());
+  if (sub_array_class == NULL) {
+    CHECK(Thread::Current()->IsExceptionPending());
+    return NULL;
+  }
+  DCHECK(sub_array_class->IsArrayClass());
+  // Create a new sub-array in every element of the array.
+  ObjectArray<Array>* object_array = new_array->AsObjectArray<Array>();
+  for (int32_t i = 0; i < array_length; i++) {
+    Array* sub_array = CreateMultiArray(sub_array_class, current_dimension, dimensions);
+    if (sub_array == NULL) {
+      CHECK(Thread::Current()->IsExceptionPending());
+      return NULL;
+    }
+    object_array->Set(i, sub_array);
+  }
+  return new_array;
+}
+
+// Create a multi-dimensional array of Objects or primitive types.
+//
+// We have to generate the names for X[], X[][], X[][][], and so on.  The
+// easiest way to deal with that is to create the full name once and then
+// subtract pieces off.  Besides, we want to start with the outermost
+// piece and work our way in.
+jobject Array_createMultiArray(JNIEnv* env, jclass, jclass javaElementClass, jobject javaDimArray) {
+  DCHECK(javaElementClass != NULL);
+  Class* element_class = Decode<Class*>(env, javaElementClass);
+  DCHECK(element_class->IsClass());
+  DCHECK(javaDimArray != NULL);
+  Object* dimensions_obj = Decode<Class*>(env, javaDimArray);
+  DCHECK(dimensions_obj->IsArrayInstance());
+  DCHECK(dimensions_obj->GetClass()->GetDescriptor()->Equals("[I"));
+  IntArray* dimensions_array = down_cast<IntArray*>(dimensions_obj);
+
+  // Verify dimensions.
+  //
+  // The caller is responsible for verifying that "dimArray" is non-null
+  // and has a length > 0 and <= 255.
+  int num_dimensions = dimensions_array->GetLength();
+  DCHECK_GT(num_dimensions, 0);
+  DCHECK_LE(num_dimensions, 255);
+
+  for (int i = 0; i < num_dimensions; i++) {
+    if (dimensions_array->Get(i) < 0) {
+      UNIMPLEMENTED(FATAL) << "ThrowNegativeArraySizeException(dimensions[i])";
+      return NULL;
+    }
+  }
+
+  // Generate the full name of the array class.
+  std::string descriptor(num_dimensions, '[');
+  descriptor += element_class->GetDescriptor()->ToModifiedUtf8();
+
+  // Find/generate the array class.
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  Class* array_class = class_linker->FindClass(descriptor, element_class->GetClassLoader());
+  if (array_class == NULL) {
+    CHECK(Thread::Current()->IsExceptionPending());
+    return NULL;
+  }
+  // create the array
+  Array* new_array = CreateMultiArray(array_class, 0, dimensions_array);
+  if (new_array == NULL) {
+    CHECK(Thread::Current()->IsExceptionPending());
+    return NULL;
+  }
+  return AddLocalReference<jobject>(env, new_array);
+}
+
+jobject Array_createObjectArray(JNIEnv* env, jclass, jclass javaElementClass, jint length)
+{
+  DCHECK(javaElementClass != NULL);
+  Class* element_class = Decode<Class*>(env, javaElementClass);
+  if (length < 0) {
+    UNIMPLEMENTED(FATAL) << "ThrowNegativeArraySizeException(length)";
+    return NULL;
+  }
+  std::string descriptor;
+  descriptor += '[';
+  descriptor += element_class->GetDescriptor()->ToModifiedUtf8();
+
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  Class* array_class = class_linker->FindClass(descriptor, element_class->GetClassLoader());
+  if (array_class == NULL) {
+    CHECK(Thread::Current()->IsExceptionPending());
+    return NULL;
+  }
+  DCHECK(array_class->IsArrayClass());
+  Array* new_array = Array::Alloc(array_class, length);
+  if (new_array == NULL) {
+    CHECK(Thread::Current()->IsExceptionPending());
+    return NULL;
+  }
+  return AddLocalReference<jobject>(env, new_array);
+}
+
+static JNINativeMethod gMethods[] = {
+  NATIVE_METHOD(Array, createMultiArray, "(Ljava/lang/Class;[I)Ljava/lang/Object;"),
+  NATIVE_METHOD(Array, createObjectArray, "(Ljava/lang/Class;I)Ljava/lang/Object;"),
+};
+
+}  // namespace
+
+void register_java_lang_reflect_Array(JNIEnv* env) {
+  jniRegisterNativeMethods(env, "java/lang/reflect/Array", gMethods, NELEM(gMethods));
+}
+
+}  // namespace art
diff --git a/src/jni_internal_test.cc b/src/jni_internal_test.cc
index 8572e40..067d36b 100644
--- a/src/jni_internal_test.cc
+++ b/src/jni_internal_test.cc
@@ -605,7 +605,7 @@
 }
 
 TEST_F(JniInternalTest, GetObjectArrayElement_SetObjectArrayElement) {
-  jclass c = env_->FindClass("[Ljava/lang/Object;");
+  jclass c = env_->FindClass("java/lang/Object");
   ASSERT_TRUE(c != NULL);
 
   jobjectArray array = env_->NewObjectArray(1, c, NULL);
diff --git a/src/object.cc b/src/object.cc
index 7f247c7..6490797 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -794,52 +794,29 @@
 // Don't forget about primitive types.
 //   Object[]         = int[] --> false
 //
-bool Class::IsArrayAssignableFromArray(const Class* klass) const {
+bool Class::IsArrayAssignableFromArray(const Class* src) const {
   DCHECK(IsArrayClass());
-  DCHECK(klass->IsArrayClass());
-  DCHECK_GT(GetArrayRank(), 0);
-  DCHECK_GT(klass->GetArrayRank(), 0);
-  DCHECK(GetComponentType() != NULL);
-  DCHECK(klass->GetComponentType() != NULL);
-  if (GetArrayRank() > klass->GetArrayRank()) {
-    // Too many []s.
-    return false;
-  }
-  if (GetArrayRank() == klass->GetArrayRank()) {
-    return GetComponentType()->IsAssignableFrom(klass->GetComponentType());
-  }
-  DCHECK_LT(GetArrayRank(), klass->GetArrayRank());
-  // The thing we might be assignable from has more dimensions.  We
-  // must be an Object or array of Object, or a standard array
-  // interface or array of standard array interfaces (the standard
-  // interfaces being java/lang/Cloneable and java/io/Serializable).
-  if (GetComponentType()->IsInterface()) {
-    // See if we implement our component type.  We know the
-    // base element is an interface; if the array class implements
-    // it, we know it's a standard array interface.
-    return Implements(GetComponentType());
-  }
-  // See if this is an array of Object, Object[], etc.
-  return GetComponentType()->IsObjectClass();
+  DCHECK(src->IsArrayClass());
+  return GetComponentType()->IsAssignableFrom(src->GetComponentType());
 }
 
-bool Class::IsAssignableFromArray(const Class* klass) const {
+bool Class::IsAssignableFromArray(const Class* src) const {
   DCHECK(!IsInterface());  // handled first in IsAssignableFrom
-  DCHECK(klass->IsArrayClass());
+  DCHECK(src->IsArrayClass());
   if (!IsArrayClass()) {
     // If "this" is not also an array, it must be Object.
-    // klass's super should be java_lang_Object, since it is an array.
-    Class* java_lang_Object = klass->GetSuperClass();
+    // src's super should be java_lang_Object, since it is an array.
+    Class* java_lang_Object = src->GetSuperClass();
     DCHECK(java_lang_Object != NULL);
     DCHECK(java_lang_Object->GetSuperClass() == NULL);
     return this == java_lang_Object;
   }
-  return IsArrayAssignableFromArray(klass);
+  return IsArrayAssignableFromArray(src);
 }
 
 bool Class::IsSubClass(const Class* klass) const {
   DCHECK(!IsInterface());
-  DCHECK(!klass->IsArrayClass());
+  DCHECK(!IsArrayClass());
   const Class* current = this;
   do {
     if (current == klass) {
diff --git a/src/object.h b/src/object.h
index 055e6a9..a04fcbb 100644
--- a/src/object.h
+++ b/src/object.h
@@ -413,7 +413,7 @@
   uint32_t monitor_;
 
   friend class ImageWriter;  // for abusing monitor_ directly
-  friend class ObjectOffsets;  // for verifying offset information
+  friend struct ObjectOffsets;  // for verifying offset information
   DISALLOW_IMPLICIT_CONSTRUCTORS(Object);
 };
 
@@ -1386,23 +1386,10 @@
   size_t PrimitiveSize() const;
 
   bool IsArrayClass() const {
-    return GetArrayRank() != 0;
-  }
-
-  int32_t GetArrayRank() const {
-    int32_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, array_rank_),
-                                false);
-    return result;
-  }
-
-  void SetArrayRank(int32_t new_array_rank) {
-    DCHECK_EQ(0, GetArrayRank());
-    SetField32(OFFSET_OF_OBJECT_MEMBER(Class, array_rank_), new_array_rank,
-               false);
+    return GetComponentType() != NULL;
   }
 
   Class* GetComponentType() const {
-    DCHECK(IsArrayClass());
     return GetFieldObject<Class*>(
         OFFSET_OF_OBJECT_MEMBER(Class, component_type_), false);
   }
@@ -1499,20 +1486,20 @@
     return that->IsPublic() || this->IsInSamePackage(that);
   }
 
-  bool IsAssignableFrom(const Class* klass) const {
-    DCHECK(klass != NULL);
-    if (this == klass) {
+  bool IsAssignableFrom(const Class* src) const {
+    DCHECK(src != NULL);
+    if (this == src) {
       // Can always assign to things of the same type
       return true;
     } else if (IsObjectClass()) {
       // Can assign any reference to java.lang.Object
-      return !klass->IsPrimitive();
+      return !src->IsPrimitive();
     } else if (IsInterface()) {
-      return klass->Implements(this);
-    } else if (klass->IsArrayClass()) {
-      return IsAssignableFromArray(klass);
+      return src->Implements(this);
+    } else if (src->IsArrayClass()) {
+      return IsAssignableFromArray(src);
     } else {
-      return klass->IsSubClass(this);
+      return src->IsSubClass(this);
     }
   }
 
@@ -1912,9 +1899,8 @@
   // defining class loader, or NULL for the "bootstrap" system loader
   const ClassLoader* class_loader_;
 
-  // For array classes, the class object for base element, for
-  // instanceof/checkcast (for String[][][], this will be String).
-  // Otherwise, NULL.
+  // For array classes, the component class object for instanceof/checkcast
+  // (for String[][][], this will be String[][]). NULL for non-array classes.
   Class* component_type_;
 
   // descriptor for the class such as "Ljava/lang/Class;" or "[C"
@@ -1988,10 +1974,6 @@
   // access flags; low 16 bits are defined by VM spec
   uint32_t access_flags_;
 
-  // For array classes, the number of array dimensions, e.g. int[][]
-  // is 2.  Otherwise 0.
-  int32_t array_rank_;
-
   // Total class size; used when allocating storage on gc heap.
   size_t class_size_;
 
@@ -2243,6 +2225,7 @@
 
 class MANAGED ClassClass : public Class {
  private:
+  int32_t padding_;
   int64_t serialVersionUID_;
   friend struct ClassClassOffsets;  // for verifying offset information
   DISALLOW_IMPLICIT_CONSTRUCTORS(ClassClass);
@@ -2252,8 +2235,8 @@
  private:
   CharArray* ASCII_;
   Object* CASE_INSENSITIVE_ORDER_;
-  int64_t serialVersionUID_;
   uint32_t REPLACEMENT_CHAR_;
+  int64_t serialVersionUID_;
   friend struct StringClassOffsets;  // for verifying offset information
   DISALLOW_IMPLICIT_CONSTRUCTORS(StringClass);
 };
diff --git a/src/object_test.cc b/src/object_test.cc
index 3c8ba5c..9b6897d 100644
--- a/src/object_test.cc
+++ b/src/object_test.cc
@@ -321,6 +321,11 @@
   EXPECT_FALSE(x->InstanceOf(Y));
   EXPECT_TRUE(y->InstanceOf(X));
   EXPECT_TRUE(y->InstanceOf(Y));
+
+  Class* Class_class = class_linker_->FindSystemClass("Ljava/lang/Class;");
+  Class* Object_array_class = class_linker_->FindSystemClass("[Ljava/lang/Object;");
+  EXPECT_FALSE(Class_class->InstanceOf(Object_array_class));
+  EXPECT_TRUE(Object_array_class->InstanceOf(Class_class));
 }
 
 TEST_F(ObjectTest, IsAssignableFrom) {
diff --git a/src/runtime.cc b/src/runtime.cc
index b9120fa..de94b3d 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -465,7 +465,7 @@
   REGISTER(register_java_lang_Throwable);
   //REGISTER(register_java_lang_VMClassLoader);
   //REGISTER(register_java_lang_reflect_AccessibleObject);
-  //REGISTER(register_java_lang_reflect_Array);
+  REGISTER(register_java_lang_reflect_Array);
   //REGISTER(register_java_lang_reflect_Constructor);
   REGISTER(register_java_lang_reflect_Field);
   REGISTER(register_java_lang_reflect_Method);