Merge "Temporarily disable test E"
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 15cc634..db0e9ac 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -4977,6 +4977,7 @@
   DCHECK(c.Get() != nullptr);
   if (c->IsInitialized()) {
     EnsureSkipAccessChecksMethods(c);
+    self->AssertNoPendingException();
     return true;
   }
   const bool success = InitializeClass(self, c, can_init_fields, can_init_parents);
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index f58af5a..5bdb36c 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -418,26 +418,6 @@
   (*icu_cleanup_fn)();
 
   Runtime::Current()->GetHeap()->VerifyHeap();  // Check for heap corruption after the test
-
-  // Manually closing the JNI libraries.
-  // Runtime does not support repeatedly doing JNI->CreateVM, thus we need to manually clean up the
-  // dynamic linking loader so that gtests would not fail.
-  // Bug: 25785594
-  if (runtime_->IsStarted()) {
-    {
-      // We retrieve the handle by calling dlopen on the library. To close it, we need to call
-      // dlclose twice, the first time to undo our dlopen and the second time to actually unload it.
-      // See man dlopen.
-      void* handle = dlopen("libjavacore.so", RTLD_LAZY);
-      dlclose(handle);
-      CHECK_EQ(0, dlclose(handle));
-    }
-    {
-      void* handle = dlopen("libopenjdkd.so", RTLD_LAZY);
-      dlclose(handle);
-      CHECK_EQ(0, dlclose(handle));
-    }
-  }
 }
 
 static std::string GetDexFileName(const std::string& jar_prefix, bool host) {
diff --git a/runtime/gc/heap-inl.h b/runtime/gc/heap-inl.h
index 6aed61a..b0ca18e 100644
--- a/runtime/gc/heap-inl.h
+++ b/runtime/gc/heap-inl.h
@@ -49,6 +49,7 @@
     // done in the runnable state where suspension is expected.
     CHECK_EQ(self->GetState(), kRunnable);
     self->AssertThreadSuspensionIsAllowable();
+    self->AssertNoPendingException();
   }
   // Need to check that we arent the large object allocator since the large object allocation code
   // path this function. If we didn't check we would have an infinite loop.
diff --git a/runtime/java_vm_ext.cc b/runtime/java_vm_ext.cc
index d983a9f..c216412 100644
--- a/runtime/java_vm_ext.cc
+++ b/runtime/java_vm_ext.cc
@@ -74,6 +74,10 @@
     if (self != nullptr) {
       self->GetJniEnv()->DeleteWeakGlobalRef(class_loader_);
     }
+
+    if (!needs_native_bridge_) {
+      android::CloseNativeLibrary(handle_);
+    }
   }
 
   jweak GetClassLoader() const {
@@ -271,8 +275,7 @@
       REQUIRES(!Locks::jni_libraries_lock_)
       SHARED_REQUIRES(Locks::mutator_lock_) {
     ScopedObjectAccessUnchecked soa(Thread::Current());
-    typedef void (*JNI_OnUnloadFn)(JavaVM*, void*);
-    std::vector<JNI_OnUnloadFn> unload_functions;
+    std::vector<SharedLibrary*> unload_libraries;
     {
       MutexLock mu(soa.Self(), *Locks::jni_libraries_lock_);
       for (auto it = libraries_.begin(); it != libraries_.end(); ) {
@@ -283,15 +286,7 @@
         // the native libraries of the boot class loader.
         if (class_loader != nullptr &&
             soa.Self()->IsJWeakCleared(class_loader)) {
-          void* const sym = library->FindSymbol("JNI_OnUnload", nullptr);
-          if (sym == nullptr) {
-            VLOG(jni) << "[No JNI_OnUnload found in \"" << library->GetPath() << "\"]";
-          } else {
-            VLOG(jni) << "[JNI_OnUnload found for \"" << library->GetPath() << "\"]";
-            JNI_OnUnloadFn jni_on_unload = reinterpret_cast<JNI_OnUnloadFn>(sym);
-            unload_functions.push_back(jni_on_unload);
-          }
-          delete library;
+          unload_libraries.push_back(library);
           it = libraries_.erase(it);
         } else {
           ++it;
@@ -299,9 +294,17 @@
       }
     }
     // Do this without holding the jni libraries lock to prevent possible deadlocks.
-    for (JNI_OnUnloadFn fn : unload_functions) {
-      VLOG(jni) << "Calling JNI_OnUnload";
-      (*fn)(soa.Vm(), nullptr);
+    typedef void (*JNI_OnUnloadFn)(JavaVM*, void*);
+    for (auto library : unload_libraries) {
+      void* const sym = library->FindSymbol("JNI_OnUnload", nullptr);
+      if (sym == nullptr) {
+        VLOG(jni) << "[No JNI_OnUnload found in \"" << library->GetPath() << "\"]";
+      } else {
+        VLOG(jni) << "[JNI_OnUnload found for \"" << library->GetPath() << "\"]: Calling...";
+        JNI_OnUnloadFn jni_on_unload = reinterpret_cast<JNI_OnUnloadFn>(sym);
+        jni_on_unload(soa.Vm(), nullptr);
+      }
+      delete library;
     }
   }
 
diff --git a/test/136-daemon-jni-shutdown/daemon_jni_shutdown.cc b/test/136-daemon-jni-shutdown/daemon_jni_shutdown.cc
index c9110a9..b729301 100644
--- a/test/136-daemon-jni-shutdown/daemon_jni_shutdown.cc
+++ b/test/136-daemon-jni-shutdown/daemon_jni_shutdown.cc
@@ -27,8 +27,20 @@
 namespace {
 
 static volatile std::atomic<bool> vm_was_shutdown(false);
+static const int kThreadCount = 4;
+
+static std::atomic<int> barrier_count(kThreadCount + 1);
+
+static void JniThreadBarrierWait() {
+  barrier_count--;
+  while (barrier_count.load() != 0) {
+    usleep(1000);
+  }
+}
 
 extern "C" JNIEXPORT void JNICALL Java_Main_waitAndCallIntoJniEnv(JNIEnv* env, jclass) {
+  // Wait for all threads to enter JNI together.
+  JniThreadBarrierWait();
   // Wait until the runtime is shutdown.
   while (!vm_was_shutdown.load()) {
     usleep(1000);
@@ -40,6 +52,8 @@
 
 // NO_RETURN does not work with extern "C" for target builds.
 extern "C" JNIEXPORT void JNICALL Java_Main_destroyJavaVMAndExit(JNIEnv* env, jclass) {
+  // Wait for all threads to enter JNI together.
+  JniThreadBarrierWait();
   // Fake up the managed stack so we can detach.
   Thread* const self = Thread::Current();
   self->SetTopOfStack(nullptr);