Move more Class annotations to native.

Art side of this change. There is also a corresponding Libcore change.

Seeing speedup in AnnotatedElementBenchmark.
GetDeclaredClasses	 21.61x
GetDeclaringClass	108.73x
GetEnclosingClass	 87.81x
GetEnclosingConstructor	 23.35x
GetEnclosingMethod	 22.71x
GetModifiers		152.47x
GetSimpleName		106.11x
IsAnonymousClass	 91.28x
IsLocalClass		 51.95x

Change-Id: I2b7f7eb7785fc20671fd7c338ffa9c7048a44a48
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index 213f25d..29413bf 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -1132,7 +1132,7 @@
   return ProcessAnnotationSet(field_class, annotation_set, kDexVisibilityRuntime);
 }
 
-mirror::ObjectArray<mirror::Object>* DexFile::GetSignatureAnnotationForField(ArtField* field)
+mirror::ObjectArray<mirror::String>* DexFile::GetSignatureAnnotationForField(ArtField* field)
     const {
   const AnnotationSetItem* annotation_set = FindAnnotationSetForField(field);
   if (annotation_set == nullptr) {
@@ -1253,7 +1253,7 @@
   return ProcessAnnotationSet(method_class, annotation_set, kDexVisibilityRuntime);
 }
 
-mirror::ObjectArray<mirror::Object>* DexFile::GetExceptionTypesForMethod(ArtMethod* method) const {
+mirror::ObjectArray<mirror::Class>* DexFile::GetExceptionTypesForMethod(ArtMethod* method) const {
   const AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method);
   if (annotation_set == nullptr) {
     return nullptr;
@@ -1289,7 +1289,7 @@
   Handle<mirror::Class> method_class(hs.NewHandle(method->GetDeclaringClass()));
   const AnnotationItem* annotation_item = GetAnnotationItemFromAnnotationSet(
       method_class, annotation_set, kDexVisibilityRuntime, annotation_class);
-  return (annotation_item != nullptr);
+  return annotation_item != nullptr;
 }
 
 const DexFile::AnnotationSetItem* DexFile::FindAnnotationSetForClass(Handle<mirror::Class> klass)
@@ -1317,6 +1317,153 @@
   return ProcessAnnotationSet(klass, annotation_set, kDexVisibilityRuntime);
 }
 
+mirror::ObjectArray<mirror::Class>* DexFile::GetDeclaredClasses(Handle<mirror::Class> klass) const {
+  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass);
+  if (annotation_set == nullptr) {
+    return nullptr;
+  }
+  const AnnotationItem* annotation_item = SearchAnnotationSet(
+      annotation_set, "Ldalvik/annotation/MemberClasses;", kDexVisibilitySystem);
+  if (annotation_item == nullptr) {
+    return nullptr;
+  }
+  StackHandleScope<1> hs(Thread::Current());
+  mirror::Class* class_class = mirror::Class::GetJavaLangClass();
+  Handle<mirror::Class> class_array_class(hs.NewHandle(
+      Runtime::Current()->GetClassLinker()->FindArrayClass(hs.Self(), &class_class)));
+  if (class_array_class.Get() == nullptr) {
+    return nullptr;
+  }
+  mirror::Object* obj = GetAnnotationValue(
+      klass, annotation_item, "value", class_array_class, kDexAnnotationArray);
+  if (obj == nullptr) {
+    return nullptr;
+  }
+  return obj->AsObjectArray<mirror::Class>();
+}
+
+mirror::Class* DexFile::GetDeclaringClass(Handle<mirror::Class> klass) const {
+  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass);
+  if (annotation_set == nullptr) {
+    return nullptr;
+  }
+  const AnnotationItem* annotation_item = SearchAnnotationSet(
+      annotation_set, "Ldalvik/annotation/EnclosingClass;", kDexVisibilitySystem);
+  if (annotation_item == nullptr) {
+    return nullptr;
+  }
+  mirror::Object* obj = GetAnnotationValue(
+      klass, annotation_item, "value", NullHandle<mirror::Class>(), kDexAnnotationType);
+  if (obj == nullptr) {
+    return nullptr;
+  }
+  return obj->AsClass();
+}
+
+mirror::Class* DexFile::GetEnclosingClass(Handle<mirror::Class> klass) const {
+  mirror::Class* declaring_class = GetDeclaringClass(klass);
+  if (declaring_class != nullptr) {
+    return declaring_class;
+  }
+  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass);
+  if (annotation_set == nullptr) {
+    return nullptr;
+  }
+  const AnnotationItem* annotation_item = SearchAnnotationSet(
+      annotation_set, "Ldalvik/annotation/EnclosingMethod;", kDexVisibilitySystem);
+  if (annotation_item == nullptr) {
+    return nullptr;
+  }
+  const uint8_t* annotation = SearchEncodedAnnotation(annotation_item->annotation_, "value");
+  if (annotation == nullptr) {
+    return nullptr;
+  }
+  AnnotationValue annotation_value;
+  if (!ProcessAnnotationValue(
+      klass, &annotation, &annotation_value, NullHandle<mirror::Class>(), kAllRaw)) {
+    return nullptr;
+  }
+  if (annotation_value.type_ != kDexAnnotationMethod) {
+    return nullptr;
+  }
+  StackHandleScope<2> hs(Thread::Current());
+  Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
+  Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
+  ArtMethod* method = Runtime::Current()->GetClassLinker()->ResolveMethodWithoutInvokeType(
+      klass->GetDexFile(), annotation_value.value_.GetI(), dex_cache, class_loader);
+  if (method == nullptr) {
+    return nullptr;
+  }
+  return method->GetDeclaringClass();
+}
+
+mirror::Object* DexFile::GetEnclosingMethod(Handle<mirror::Class> klass) const {
+  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass);
+  if (annotation_set == nullptr) {
+    return nullptr;
+  }
+  const AnnotationItem* annotation_item = SearchAnnotationSet(
+      annotation_set, "Ldalvik/annotation/EnclosingMethod;", kDexVisibilitySystem);
+  if (annotation_item == nullptr) {
+    return nullptr;
+  }
+  return GetAnnotationValue(
+      klass, annotation_item, "value", NullHandle<mirror::Class>(), kDexAnnotationMethod);
+}
+
+bool DexFile::GetInnerClass(Handle<mirror::Class> klass, mirror::String** name) const {
+  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass);
+  if (annotation_set == nullptr) {
+    return false;
+  }
+  const AnnotationItem* annotation_item = SearchAnnotationSet(
+      annotation_set, "Ldalvik/annotation/InnerClass;", kDexVisibilitySystem);
+  if (annotation_item == nullptr) {
+    return false;
+  }
+  const uint8_t* annotation = SearchEncodedAnnotation(annotation_item->annotation_, "name");
+  if (annotation == nullptr) {
+    return false;
+  }
+  AnnotationValue annotation_value;
+  if (!ProcessAnnotationValue(
+      klass, &annotation, &annotation_value, NullHandle<mirror::Class>(), kAllObjects)) {
+    return false;
+  }
+  if (annotation_value.type_ != kDexAnnotationNull &&
+      annotation_value.type_ != kDexAnnotationString) {
+    return false;
+  }
+  *name = down_cast<mirror::String*>(annotation_value.value_.GetL());
+  return true;
+}
+
+bool DexFile::GetInnerClassFlags(Handle<mirror::Class> klass, uint32_t* flags) const {
+  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass);
+  if (annotation_set == nullptr) {
+    return false;
+  }
+  const AnnotationItem* annotation_item = SearchAnnotationSet(
+      annotation_set, "Ldalvik/annotation/InnerClass;", kDexVisibilitySystem);
+  if (annotation_item == nullptr) {
+    return false;
+  }
+  const uint8_t* annotation = SearchEncodedAnnotation(annotation_item->annotation_, "accessFlags");
+  if (annotation == nullptr) {
+    return false;
+  }
+  AnnotationValue annotation_value;
+  if (!ProcessAnnotationValue(
+      klass, &annotation, &annotation_value, NullHandle<mirror::Class>(), kAllRaw)) {
+    return false;
+  }
+  if (annotation_value.type_ != kDexAnnotationInt) {
+    return false;
+  }
+  *flags = annotation_value.value_.GetI();
+  return true;
+}
+
 bool DexFile::IsClassAnnotationPresent(Handle<mirror::Class> klass,
                                        Handle<mirror::Class> annotation_class) const {
   const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass);
@@ -1325,7 +1472,7 @@
   }
   const AnnotationItem* annotation_item = GetAnnotationItemFromAnnotationSet(
       klass, annotation_set, kDexVisibilityRuntime, annotation_class);
-  return (annotation_item != nullptr);
+  return annotation_item != nullptr;
 }
 
 mirror::Object* DexFile::CreateAnnotationMember(Handle<mirror::Class> klass,
@@ -1440,7 +1587,7 @@
   return annotation_value.value_.GetL();
 }
 
-mirror::ObjectArray<mirror::Object>* DexFile::GetSignatureValue(Handle<mirror::Class> klass,
+mirror::ObjectArray<mirror::String>* DexFile::GetSignatureValue(Handle<mirror::Class> klass,
     const AnnotationSetItem* annotation_set) const {
   StackHandleScope<1> hs(Thread::Current());
   const AnnotationItem* annotation_item =
@@ -1451,15 +1598,18 @@
   mirror::Class* string_class = mirror::String::GetJavaLangString();
   Handle<mirror::Class> string_array_class(hs.NewHandle(
       Runtime::Current()->GetClassLinker()->FindArrayClass(Thread::Current(), &string_class)));
+  if (string_array_class.Get() == nullptr) {
+    return nullptr;
+  }
   mirror::Object* obj =
       GetAnnotationValue(klass, annotation_item, "value", string_array_class, kDexAnnotationArray);
   if (obj == nullptr) {
     return nullptr;
   }
-  return obj->AsObjectArray<mirror::Object>();
+  return obj->AsObjectArray<mirror::String>();
 }
 
-mirror::ObjectArray<mirror::Object>* DexFile::GetThrowsValue(Handle<mirror::Class> klass,
+mirror::ObjectArray<mirror::Class>* DexFile::GetThrowsValue(Handle<mirror::Class> klass,
     const AnnotationSetItem* annotation_set) const {
   StackHandleScope<1> hs(Thread::Current());
   const AnnotationItem* annotation_item =
@@ -1470,12 +1620,15 @@
   mirror::Class* class_class = mirror::Class::GetJavaLangClass();
   Handle<mirror::Class> class_array_class(hs.NewHandle(
       Runtime::Current()->GetClassLinker()->FindArrayClass(Thread::Current(), &class_class)));
+  if (class_array_class.Get() == nullptr) {
+    return nullptr;
+  }
   mirror::Object* obj =
       GetAnnotationValue(klass, annotation_item, "value", class_array_class, kDexAnnotationArray);
   if (obj == nullptr) {
     return nullptr;
   }
-  return obj->AsObjectArray<mirror::Object>();
+  return obj->AsObjectArray<mirror::Class>();
 }
 
 mirror::ObjectArray<mirror::Object>* DexFile::ProcessAnnotationSet(Handle<mirror::Class> klass,
@@ -1507,6 +1660,8 @@
     if (annotation_obj != nullptr) {
       result->SetWithoutChecks<false>(dest_index, annotation_obj);
       ++dest_index;
+    } else if (self->IsExceptionPending()) {
+      return nullptr;
     }
   }
 
@@ -1516,6 +1671,10 @@
 
   mirror::ObjectArray<mirror::Object>* trimmed_result =
       mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_array_class.Get(), dest_index);
+  if (trimmed_result == nullptr) {
+    return nullptr;
+  }
+
   for (uint32_t i = 0; i < dest_index; ++i) {
     mirror::Object* obj = result->GetWithoutChecks(i);
     trimmed_result->SetWithoutChecks<false>(i, obj);
@@ -1533,6 +1692,9 @@
       soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_annotation_Annotation__array);
   mirror::Class* annotation_array_array_class =
       Runtime::Current()->GetClassLinker()->FindArrayClass(self, &annotation_array_class);
+  if (annotation_array_array_class == nullptr) {
+    return nullptr;
+  }
   Handle<mirror::ObjectArray<mirror::Object>> annotation_array_array(hs.NewHandle(
       mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_array_array_class, size)));
   if (annotation_array_array.Get() == nullptr) {
@@ -1625,9 +1787,8 @@
             klass->GetDexFile(), index, klass.Get());
         set_object = true;
         if (element_object == nullptr) {
-          self->ClearException();
-          const char* msg = StringByTypeIdx(index);
-          self->ThrowNewException("Ljava/lang/TypeNotPresentException;", msg);
+          // TODO: Put a TypeNotFoundExceptionProxy instead of throwing here.
+          return false;
         }
       }
       break;
@@ -1831,8 +1992,10 @@
       soa.Decode<mirror::Class*>(WellKnownClasses::libcore_reflect_AnnotationMember);
   mirror::Class* annotation_member_array_class =
       class_linker->FindArrayClass(self, &annotation_member_class);
+  if (annotation_member_array_class == nullptr) {
+    return nullptr;
+  }
   mirror::ObjectArray<mirror::Object>* element_array = nullptr;
-
   if (size > 0) {
     element_array =
         mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_member_array_class, size);
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index 8928321..98d4e59 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -931,7 +931,7 @@
       const SHARED_REQUIRES(Locks::mutator_lock_);
   mirror::ObjectArray<mirror::Object>* GetAnnotationsForField(ArtField* field) const
       SHARED_REQUIRES(Locks::mutator_lock_);
-  mirror::ObjectArray<mirror::Object>* GetSignatureAnnotationForField(ArtField* field) const
+  mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForField(ArtField* field) const
       SHARED_REQUIRES(Locks::mutator_lock_);
   bool IsFieldAnnotationPresent(ArtField* field, Handle<mirror::Class> annotation_class) const
       SHARED_REQUIRES(Locks::mutator_lock_);
@@ -946,7 +946,7 @@
       const SHARED_REQUIRES(Locks::mutator_lock_);
   mirror::ObjectArray<mirror::Object>* GetAnnotationsForMethod(ArtMethod* method) const
       SHARED_REQUIRES(Locks::mutator_lock_);
-  mirror::ObjectArray<mirror::Object>* GetExceptionTypesForMethod(ArtMethod* method) const
+  mirror::ObjectArray<mirror::Class>* GetExceptionTypesForMethod(ArtMethod* method) const
       SHARED_REQUIRES(Locks::mutator_lock_);
   mirror::ObjectArray<mirror::Object>* GetParameterAnnotations(ArtMethod* method) const
       SHARED_REQUIRES(Locks::mutator_lock_);
@@ -960,6 +960,18 @@
       SHARED_REQUIRES(Locks::mutator_lock_);
   mirror::ObjectArray<mirror::Object>* GetAnnotationsForClass(Handle<mirror::Class> klass) const
       SHARED_REQUIRES(Locks::mutator_lock_);
+  mirror::ObjectArray<mirror::Class>* GetDeclaredClasses(Handle<mirror::Class> klass) const
+      SHARED_REQUIRES(Locks::mutator_lock_);
+  mirror::Class* GetDeclaringClass(Handle<mirror::Class> klass) const
+      SHARED_REQUIRES(Locks::mutator_lock_);
+  mirror::Class* GetEnclosingClass(Handle<mirror::Class> klass) const
+      SHARED_REQUIRES(Locks::mutator_lock_);
+  mirror::Object* GetEnclosingMethod(Handle<mirror::Class> klass) const
+      SHARED_REQUIRES(Locks::mutator_lock_);
+  bool GetInnerClass(Handle<mirror::Class> klass, mirror::String** name) const
+      SHARED_REQUIRES(Locks::mutator_lock_);
+  bool GetInnerClassFlags(Handle<mirror::Class> klass, uint32_t* flags) const
+      SHARED_REQUIRES(Locks::mutator_lock_);
   bool IsClassAnnotationPresent(Handle<mirror::Class> klass, Handle<mirror::Class> annotation_class)
       const SHARED_REQUIRES(Locks::mutator_lock_);
 
@@ -983,11 +995,11 @@
                                      Handle<mirror::Class> array_class,
                                      uint32_t expected_type) const
       SHARED_REQUIRES(Locks::mutator_lock_);
-  mirror::ObjectArray<mirror::Object>* GetSignatureValue(Handle<mirror::Class> klass,
+  mirror::ObjectArray<mirror::String>* GetSignatureValue(Handle<mirror::Class> klass,
                                                          const AnnotationSetItem* annotation_set)
       const SHARED_REQUIRES(Locks::mutator_lock_);
-  mirror::ObjectArray<mirror::Object>* GetThrowsValue(Handle<mirror::Class> klass,
-                                                      const AnnotationSetItem* annotation_set) const
+  mirror::ObjectArray<mirror::Class>* GetThrowsValue(Handle<mirror::Class> klass,
+                                                     const AnnotationSetItem* annotation_set) const
       SHARED_REQUIRES(Locks::mutator_lock_);
   mirror::ObjectArray<mirror::Object>* ProcessAnnotationSet(Handle<mirror::Class> klass,
                                                             const AnnotationSetItem* annotation_set,
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index 7e464e9..8fd6849 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -430,7 +430,7 @@
   ScopedFastNativeObjectAccess soa(env);
   StackHandleScope<2> hs(soa.Self());
   Handle<mirror::Class> klass(hs.NewHandle(DecodeClass(soa, javaThis)));
-  if (klass->IsProxyClass()) {
+  if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) {
     return nullptr;
   }
   Handle<mirror::Class> annotation_class(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType)));
@@ -442,7 +442,7 @@
   ScopedFastNativeObjectAccess soa(env);
   StackHandleScope<1> hs(soa.Self());
   Handle<mirror::Class> klass(hs.NewHandle(DecodeClass(soa, javaThis)));
-  if (klass->IsProxyClass()) {
+  if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) {
     // Return an empty array instead of a null pointer.
     mirror::Class* annotation_array_class =
         soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_annotation_Annotation__array);
@@ -453,18 +453,141 @@
   return soa.AddLocalReference<jobjectArray>(klass->GetDexFile().GetAnnotationsForClass(klass));
 }
 
+static jobjectArray Class_getDeclaredClasses(JNIEnv* env, jobject javaThis) {
+  ScopedFastNativeObjectAccess soa(env);
+  StackHandleScope<1> hs(soa.Self());
+  Handle<mirror::Class> klass(hs.NewHandle(DecodeClass(soa, javaThis)));
+  mirror::ObjectArray<mirror::Class>* classes = nullptr;
+  if (!klass->IsProxyClass() && klass->GetDexCache() != nullptr) {
+    classes = klass->GetDexFile().GetDeclaredClasses(klass);
+  }
+  if (classes == nullptr) {
+    // Return an empty array instead of a null pointer.
+    mirror::Class* class_class = mirror::Class::GetJavaLangClass();
+    mirror::Class* class_array_class =
+        Runtime::Current()->GetClassLinker()->FindArrayClass(soa.Self(), &class_class);
+    if (class_array_class == nullptr) {
+      return nullptr;
+    }
+    mirror::ObjectArray<mirror::Class>* empty_array =
+        mirror::ObjectArray<mirror::Class>::Alloc(soa.Self(), class_array_class, 0);
+    return soa.AddLocalReference<jobjectArray>(empty_array);
+  }
+  return soa.AddLocalReference<jobjectArray>(classes);
+}
+
+static jclass Class_getEnclosingClass(JNIEnv* env, jobject javaThis) {
+  ScopedFastNativeObjectAccess soa(env);
+  StackHandleScope<1> hs(soa.Self());
+  Handle<mirror::Class> klass(hs.NewHandle(DecodeClass(soa, javaThis)));
+  if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) {
+    return nullptr;
+  }
+  return soa.AddLocalReference<jclass>(klass->GetDexFile().GetEnclosingClass(klass));
+}
+
+static jobject Class_getEnclosingConstructorNative(JNIEnv* env, jobject javaThis) {
+  ScopedFastNativeObjectAccess soa(env);
+  StackHandleScope<1> hs(soa.Self());
+  Handle<mirror::Class> klass(hs.NewHandle(DecodeClass(soa, javaThis)));
+  if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) {
+    return nullptr;
+  }
+  mirror::Object* method = klass->GetDexFile().GetEnclosingMethod(klass);
+  if (method != nullptr) {
+    if (method->GetClass() ==
+        soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Constructor)) {
+      return soa.AddLocalReference<jobject>(method);
+    }
+  }
+  return nullptr;
+}
+
+static jobject Class_getEnclosingMethodNative(JNIEnv* env, jobject javaThis) {
+  ScopedFastNativeObjectAccess soa(env);
+  StackHandleScope<1> hs(soa.Self());
+  Handle<mirror::Class> klass(hs.NewHandle(DecodeClass(soa, javaThis)));
+  if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) {
+    return nullptr;
+  }
+  mirror::Object* method = klass->GetDexFile().GetEnclosingMethod(klass);
+  if (method != nullptr) {
+    if (method->GetClass() ==
+        soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Method)) {
+      return soa.AddLocalReference<jobject>(method);
+    }
+  }
+  return nullptr;
+}
+
+static jint Class_getInnerClassFlags(JNIEnv* env, jobject javaThis, jint defaultValue) {
+  ScopedFastNativeObjectAccess soa(env);
+  StackHandleScope<1> hs(soa.Self());
+  Handle<mirror::Class> klass(hs.NewHandle(DecodeClass(soa, javaThis)));
+  if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) {
+    return defaultValue;
+  }
+  uint32_t flags;
+  if (!klass->GetDexFile().GetInnerClassFlags(klass, &flags)) {
+    return defaultValue;
+  }
+  return flags;
+}
+
+static jstring Class_getInnerClassName(JNIEnv* env, jobject javaThis) {
+  ScopedFastNativeObjectAccess soa(env);
+  StackHandleScope<1> hs(soa.Self());
+  Handle<mirror::Class> klass(hs.NewHandle(DecodeClass(soa, javaThis)));
+  if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) {
+    return nullptr;
+  }
+  mirror::String* class_name = nullptr;
+  if (!klass->GetDexFile().GetInnerClass(klass, &class_name)) {
+    return nullptr;
+  }
+  return soa.AddLocalReference<jstring>(class_name);
+}
+
+static jboolean Class_isAnonymousClass(JNIEnv* env, jobject javaThis) {
+  ScopedFastNativeObjectAccess soa(env);
+  StackHandleScope<1> hs(soa.Self());
+  Handle<mirror::Class> klass(hs.NewHandle(DecodeClass(soa, javaThis)));
+  if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) {
+    return false;
+  }
+  mirror::String* class_name = nullptr;
+  if (!klass->GetDexFile().GetInnerClass(klass, &class_name)) {
+    return false;
+  }
+  return class_name == nullptr;
+}
+
 static jboolean Class_isDeclaredAnnotationPresent(JNIEnv* env, jobject javaThis,
                                                   jclass annotationType) {
   ScopedFastNativeObjectAccess soa(env);
   StackHandleScope<2> hs(soa.Self());
   Handle<mirror::Class> klass(hs.NewHandle(DecodeClass(soa, javaThis)));
-  if (klass->IsProxyClass()) {
+  if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) {
     return false;
   }
   Handle<mirror::Class> annotation_class(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType)));
   return klass->GetDexFile().IsClassAnnotationPresent(klass, annotation_class);
 }
 
+static jclass Class_getDeclaringClass(JNIEnv* env, jobject javaThis) {
+  ScopedFastNativeObjectAccess soa(env);
+  StackHandleScope<1> hs(soa.Self());
+  Handle<mirror::Class> klass(hs.NewHandle(DecodeClass(soa, javaThis)));
+  if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) {
+    return nullptr;
+  }
+  // Return null for anonymous classes.
+  if (Class_isAnonymousClass(env, javaThis)) {
+    return nullptr;
+  }
+  return soa.AddLocalReference<jclass>(klass->GetDexFile().GetDeclaringClass(klass));
+}
+
 static jobject Class_newInstance(JNIEnv* env, jobject javaThis) {
   ScopedFastNativeObjectAccess soa(env);
   StackHandleScope<4> hs(soa.Self());
@@ -550,6 +673,7 @@
   NATIVE_METHOD(Class, getDeclaredAnnotation,
                 "!(Ljava/lang/Class;)Ljava/lang/annotation/Annotation;"),
   NATIVE_METHOD(Class, getDeclaredAnnotations, "!()[Ljava/lang/annotation/Annotation;"),
+  NATIVE_METHOD(Class, getDeclaredClasses, "!()[Ljava/lang/Class;"),
   NATIVE_METHOD(Class, getDeclaredConstructorInternal,
                 "!([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;"),
   NATIVE_METHOD(Class, getDeclaredConstructorsInternal, "!(Z)[Ljava/lang/reflect/Constructor;"),
@@ -561,9 +685,16 @@
                 "!(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;"),
   NATIVE_METHOD(Class, getDeclaredMethodsUnchecked,
                 "!(Z)[Ljava/lang/reflect/Method;"),
+  NATIVE_METHOD(Class, getDeclaringClass, "!()Ljava/lang/Class;"),
+  NATIVE_METHOD(Class, getEnclosingClass, "!()Ljava/lang/Class;"),
+  NATIVE_METHOD(Class, getEnclosingConstructorNative, "!()Ljava/lang/reflect/Constructor;"),
+  NATIVE_METHOD(Class, getEnclosingMethodNative, "!()Ljava/lang/reflect/Method;"),
+  NATIVE_METHOD(Class, getInnerClassFlags, "!(I)I"),
+  NATIVE_METHOD(Class, getInnerClassName, "!()Ljava/lang/String;"),
   NATIVE_METHOD(Class, getNameNative, "!()Ljava/lang/String;"),
   NATIVE_METHOD(Class, getProxyInterfaces, "!()[Ljava/lang/Class;"),
   NATIVE_METHOD(Class, getPublicDeclaredFields, "!()[Ljava/lang/reflect/Field;"),
+  NATIVE_METHOD(Class, isAnonymousClass, "!()Z"),
   NATIVE_METHOD(Class, isDeclaredAnnotationPresent, "!(Ljava/lang/Class;)Z"),
   NATIVE_METHOD(Class, newInstance, "!()Ljava/lang/Object;"),
 };
diff --git a/runtime/native/java_lang_reflect_Constructor.cc b/runtime/native/java_lang_reflect_Constructor.cc
index b4b77e7..e1e9ceb 100644
--- a/runtime/native/java_lang_reflect_Constructor.cc
+++ b/runtime/native/java_lang_reflect_Constructor.cc
@@ -48,15 +48,18 @@
 static jobjectArray Constructor_getExceptionTypes(JNIEnv* env, jobject javaMethod) {
   ScopedFastNativeObjectAccess soa(env);
   ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod);
-  mirror::ObjectArray<mirror::Object>* result_array =
+  mirror::ObjectArray<mirror::Class>* result_array =
       method->GetDexFile()->GetExceptionTypesForMethod(method);
   if (result_array == nullptr) {
     // Return an empty array instead of a null pointer.
     mirror::Class* class_class = mirror::Class::GetJavaLangClass();
     mirror::Class* class_array_class =
         Runtime::Current()->GetClassLinker()->FindArrayClass(soa.Self(), &class_class);
-    mirror::ObjectArray<mirror::Object>* empty_array =
-        mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), class_array_class, 0);
+    if (class_array_class == nullptr) {
+      return nullptr;
+    }
+    mirror::ObjectArray<mirror::Class>* empty_array =
+        mirror::ObjectArray<mirror::Class>::Alloc(soa.Self(), class_array_class, 0);
     return soa.AddLocalReference<jobjectArray>(empty_array);
   } else {
     return soa.AddLocalReference<jobjectArray>(result_array);
diff --git a/runtime/native/java_lang_reflect_Method.cc b/runtime/native/java_lang_reflect_Method.cc
index 1219f85..caacba6 100644
--- a/runtime/native/java_lang_reflect_Method.cc
+++ b/runtime/native/java_lang_reflect_Method.cc
@@ -82,15 +82,18 @@
     mirror::ObjectArray<mirror::Class>* declared_exceptions = klass->GetThrows()->Get(throws_index);
     return soa.AddLocalReference<jobjectArray>(declared_exceptions->Clone(soa.Self()));
   } else {
-    mirror::ObjectArray<mirror::Object>* result_array =
+    mirror::ObjectArray<mirror::Class>* result_array =
         method->GetDexFile()->GetExceptionTypesForMethod(method);
     if (result_array == nullptr) {
       // Return an empty array instead of a null pointer
       mirror::Class* class_class = mirror::Class::GetJavaLangClass();
       mirror::Class* class_array_class =
           Runtime::Current()->GetClassLinker()->FindArrayClass(soa.Self(), &class_class);
-      mirror::ObjectArray<mirror::Object>* empty_array =
-          mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), class_array_class, 0);
+      if (class_array_class == nullptr) {
+        return nullptr;
+      }
+      mirror::ObjectArray<mirror::Class>* empty_array =
+          mirror::ObjectArray<mirror::Class>::Alloc(soa.Self(), class_array_class, 0);
       return soa.AddLocalReference<jobjectArray>(empty_array);
     } else {
       return soa.AddLocalReference<jobjectArray>(result_array);