Defer unloader JNI libraries of boot classpath as late as possible.

Also don't try to lock at this point.
A lock would run a checkpoint on threads that are dying, and this can
lead to crashes, eg:
https://build.chromium.org/p/client.art/builders/host-x86-cms/builds/4412/steps/test%20debuggable/logs/stdio

+*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
+Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR) fault addr (nil)
+OS: Linux 4.4.0-78-generic (x86_64)
+Cmdline: <unset>
+Thread: 10797 "Shutdown thread"
+Registers:
+    eax: 0x00000000    ebx: 0xf739c104    ecx: 0xf739f794    edx: 0x00000001
+    edi: 0x00000000    esi: 0x56748c54    ebp: 0xffd2bd18    esp: 0xffd2bcc0
+    eip: 0xf6c18c8c                    eflags: 0x00010246 [ PF ZF IF ]
+     cs: 0x00000023     ds: 0x0000002b     es: 0x0000002b     fs: 0x0000006b
+     gs: 0x00000063     ss: 0x0000002b
+Backtrace:
+	#00 pc 001ffc8c  /b/build/slave/host-x86-cms/build/out/host/linux-x86/lib/libartd.so (art::Thread::CheckEmptyCheckpointFromMutex()+428)
+	  art::Thread::ReadFlag(art::ThreadFlag) const
+	   art/runtime/thread.h:1089
+	  art::Thread::CheckEmptyCheckpointFromMutex()
+	   art/runtime/thread-inl.h:94
+	#01 pc 001fb40e  /b/build/slave/host-x86-cms/build/out/host/linux-x86/lib/libartd.so (art::Mutex::ExclusiveLock(art::Thread*)+462)
+	  art::Mutex::ExclusiveLock(art::Thread*)
+	   art/runtime/base/mutex.cc:382
+	#02 pc 0064d9b7  /b/build/slave/host-x86-cms/build/out/host/linux-x86/lib/libartd.so (art::Libraries::UnloadBootNativeLibraries(_JavaVM*)+103)
+	  MutexLock
+	   art/runtime/base/mutex.h:431
+	  art::Libraries::UnloadBootNativeLibraries(_JavaVM*)
+	   art/runtime/jni/java_vm_ext.cc:230

Test: 004-ThreadStress
Change-Id: I7f9b69590983ff4e3276a0ad1ef5c7453d692b04
diff --git a/runtime/jni/java_vm_ext.cc b/runtime/jni/java_vm_ext.cc
index a0c013c..f71ab6f 100644
--- a/runtime/jni/java_vm_ext.cc
+++ b/runtime/jni/java_vm_ext.cc
@@ -224,15 +224,15 @@
     STLDeleteValues(&libraries_);
   }
 
-  void UnloadBootNativeLibraries(JavaVM* vm) {
+  // NO_THREAD_SAFETY_ANALYSIS as this is during runtime shutdown, and we have
+  // no thread to lock this with.
+  void UnloadBootNativeLibraries(JavaVM* vm) const NO_THREAD_SAFETY_ANALYSIS {
+    CHECK(Thread::Current() == nullptr);
     std::vector<SharedLibrary*> unload_libraries;
-    {
-      MutexLock mu(Thread::Current(), *Locks::jni_libraries_lock_);
-      for (auto it = libraries_.begin(); it != libraries_.end(); ++it) {
-        SharedLibrary* const library = it->second;
-        if (library->GetClassLoader() == nullptr) {
-          unload_libraries.push_back(library);
-        }
+    for (auto it = libraries_.begin(); it != libraries_.end(); ++it) {
+      SharedLibrary* const library = it->second;
+      if (library->GetClassLoader() == nullptr) {
+        unload_libraries.push_back(library);
       }
     }
     UnloadLibraries(vm, unload_libraries);
@@ -508,6 +508,7 @@
 }
 
 JavaVMExt::~JavaVMExt() {
+  UnloadBootNativeLibraries();
 }
 
 // Checking "globals" and "weak_globals" usually requires locks, but we
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 1eae7ae..33e81bd 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -432,10 +432,6 @@
     thread_list_->ShutDown();
   }
 
-  // We can only unload boot classpath native libraries once all threads are terminated
-  // or suspended.
-  java_vm_->UnloadBootNativeLibraries();
-
   // TODO Maybe do some locking.
   for (auto& agent : agents_) {
     agent->Unload();