--- old/src/os/solaris/vm/os_solaris.cpp Tue May 3 04:08:09 2016 +++ new/src/os/solaris/vm/os_solaris.cpp Tue May 3 04:08:08 2016 @@ -1221,13 +1221,9 @@ void os::free_thread(OSThread* osthread) { assert(osthread != NULL, "os::free_thread but osthread not set"); + // Usually osthread will be the current thread, but during VM termination + // it might be the VMThread or (what was) the WatcherThread - // We are told to free resources of the argument thread, - // but we can only really operate on the current thread. - // The main thread must take the VMThread down synchronously - // before the main thread exits and frees up CodeHeap - guarantee((Thread::current()->osthread() == osthread - || (osthread == VMThread::vm_thread()->osthread())), "os::free_thread but not current thread"); if (Thread::current()->osthread() == osthread) { // Restore caller's signal mask sigset_t sigmask = osthread->caller_sigmask(); --- old/src/share/vm/gc/parallel/gcTaskThread.cpp Tue May 3 04:08:11 2016 +++ new/src/share/vm/gc/parallel/gcTaskThread.cpp Tue May 3 04:08:10 2016 @@ -177,4 +177,5 @@ } } } + NOT_PRODUCT(ShouldNotReachHere()); // should never terminate } --- old/src/share/vm/gc/shared/concurrentGCThread.cpp Tue May 3 04:08:13 2016 +++ new/src/share/vm/gc/shared/concurrentGCThread.cpp Tue May 3 04:08:12 2016 @@ -82,6 +82,12 @@ run_service(); terminate(); + + // Can't "delete this" before we terminate as other code + // holds references to 'this', but we must do some cleanup + // ourselves before allowing the native thread to terminate + + ThreadLocalStorage::set_thread(NULL); } void ConcurrentGCThread::stop() { --- old/src/share/vm/gc/shared/workgroup.cpp Tue May 3 04:08:15 2016 +++ new/src/share/vm/gc/shared/workgroup.cpp Tue May 3 04:08:14 2016 @@ -267,6 +267,7 @@ void AbstractGangWorker::run() { initialize(); loop(); + NOT_PRODUCT(ShouldNotReachHere()); // should never return from loop() } void AbstractGangWorker::initialize() { --- old/src/share/vm/runtime/thread.cpp Tue May 3 04:08:17 2016 +++ new/src/share/vm/runtime/thread.cpp Tue May 3 04:08:16 2016 @@ -1326,6 +1326,15 @@ _watcher_thread = NULL; Terminator_lock->notify(); } + + // Deletion is done synchronously by the thread terminating the VM + // so that the WatcherThread deletion doesn't race with that thread as it + // tears down VM resources. That means 'this' may already have been + // deallocated so we can't reference it. However we must do some cleanup + // ourselves before allowing the native thread to terminate + + ThreadLocalStorage::set_thread(NULL); + } void WatcherThread::start() { @@ -1344,6 +1353,7 @@ } void WatcherThread::stop() { + WatcherThread* watcher = NULL; { // Follow normal safepoint aware lock enter protocol since the // WatcherThread is stopped by another JavaThread. @@ -1350,7 +1360,7 @@ MutexLocker ml(PeriodicTask_lock); _should_terminate = true; - WatcherThread* watcher = watcher_thread(); + watcher = watcher_thread(); if (watcher != NULL) { // unpark the WatcherThread so it can see that it should terminate watcher->unpark(); @@ -1373,6 +1383,10 @@ Terminator_lock->wait(!Mutex::_no_safepoint_check_flag, 0, Mutex::_as_suspend_equivalent_flag); } + + // can't get here till the WatcherThread has indicated it is terminating + if (watcher != NULL) + delete watcher; } void WatcherThread::unpark() { --- old/src/share/vm/runtime/vmThread.cpp Tue May 3 04:08:19 2016 +++ new/src/share/vm/runtime/vmThread.cpp Tue May 3 04:08:18 2016 @@ -308,10 +308,14 @@ _terminate_lock->notify(); } - // Deletion must be done synchronously by the JNI DestroyJavaVM thread - // so that the VMThread deletion completes before the main thread frees - // up the CodeHeap. + // Deletion is done synchronously by the JNI DestroyJavaVM thread + // so that the VMThread deletion doesn't race with that thread as it + // tears down VM resources. That means 'this' may already have been + // deallocated so we can't reference it. However we must do some cleanup + // ourselves before allowing the native thread to terminate + ThreadLocalStorage::set_thread(NULL); + }