Merge "Fix erroneous behaviors with OOME present."
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 2d0b147..6c5679e 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1658,23 +1658,24 @@
     // size when the class becomes resolved.
     klass.Assign(AllocClass(self, SizeOfClassWithoutEmbeddedTables(dex_file, dex_class_def)));
   }
-  if (UNLIKELY(klass.Get() == NULL)) {
+  if (UNLIKELY(klass.Get() == nullptr)) {
     CHECK(self->IsExceptionPending());  // Expect an OOME.
-    return NULL;
+    return nullptr;
   }
   klass->SetDexCache(FindDexCache(dex_file));
   LoadClass(dex_file, dex_class_def, klass, class_loader.Get());
-  // Check for a pending exception during load
-  if (self->IsExceptionPending()) {
-    klass->SetStatus(mirror::Class::kStatusError, self);
-    return NULL;
-  }
   ObjectLock<mirror::Class> lock(self, klass);
+  if (self->IsExceptionPending()) {
+    // An exception occured during load, set status to erroneous while holding klass' lock in case
+    // notification is necessary.
+    klass->SetStatus(mirror::Class::kStatusError, self);
+    return nullptr;
+  }
   klass->SetClinitThreadId(self->GetTid());
 
   // Add the newly loaded class to the loaded classes table.
   mirror::Class* existing = InsertClass(descriptor, klass.Get(), Hash(descriptor));
-  if (existing != NULL) {
+  if (existing != nullptr) {
     // We failed to insert because we raced with another thread. Calling EnsureResolved may cause
     // this thread to block.
     return EnsureResolved(self, descriptor, existing);
@@ -1685,7 +1686,7 @@
   if (!LoadSuperAndInterfaces(klass, dex_file)) {
     // Loading failed.
     klass->SetStatus(mirror::Class::kStatusError, self);
-    return NULL;
+    return nullptr;
   }
   CHECK(klass->IsLoaded());
   // Link the class (if necessary)
@@ -1697,7 +1698,7 @@
   if (!LinkClass(self, descriptor, klass, interfaces, &new_class)) {
     // Linking failed.
     klass->SetStatus(mirror::Class::kStatusError, self);
-    return NULL;
+    return nullptr;
   }
   CHECK(new_class != nullptr) << descriptor;
   CHECK(new_class->IsResolved()) << descriptor;
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index e577c2c..124bdf5 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -71,7 +71,10 @@
     jthrowable cnfe = reinterpret_cast<jthrowable>(env->NewObject(WellKnownClasses::java_lang_ClassNotFoundException,
                                                                   WellKnownClasses::java_lang_ClassNotFoundException_init,
                                                                   javaName, cause.get()));
-    env->Throw(cnfe);
+    if (cnfe != nullptr) {
+      // Make sure allocation didn't fail with an OOME.
+      env->Throw(cnfe);
+    }
     return nullptr;
   }
   if (initialize) {
diff --git a/runtime/thread.cc b/runtime/thread.cc
index f888029..ba5f9d4 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -1138,7 +1138,7 @@
   if (UNLIKELY(IsExceptionPending())) {
     ScopedObjectAccess soa(Thread::Current());
     mirror::Throwable* exception = GetException(nullptr);
-    LOG(FATAL) << "Throwing new exception " << msg << " with unexpected pending exception: "
+    LOG(FATAL) << "Throwing new exception '" << msg << "' with unexpected pending exception: "
         << exception->Dump();
   }
 }