A JavaThread that is no longer on the threads list, and thus not included in safepoints should not do transitions.
V [libjvm.dylib+0x5d2f9c] HandshakeState::process_self_inner(JavaThread*)+0xf0
V [libjvm.dylib+0xbe3519] HandshakeState::process_by_self(JavaThread*)+0x39
V [libjvm.dylib+0xbe33df] ThreadStateTransition::transition_and_fence(JavaThread*, JavaThreadState, JavaThreadState)+0xbf
V [libjvm.dylib+0x9bd732] Monitor::lock(Thread*)+0x1ea
V [libjvm.dylib+0xc719e4] VMThread::wait_for_vm_thread_exit()+0x1c
V [libjvm.dylib+0xbbb317] Threads::destroy_vm()+0x1ad
V [libjvm.dylib+0x6f50c3] jni_DestroyJavaVM+0x16d
C [libjli.dylib+0x4639] JavaMain+0xa14
The above stack trace shows that the JavaThread calling
VMThread::wait_for_vm_thread_exit() is acquiring a lock
and following the safepoint protocol. However, at the point
that VMThread::wait_for_vm_thread_exit() is called, the
JavaThread has already exited:
src/hotspot/share/runtime/thread.cpp:
before_exit(thread);
thread->exit(true);
// Stop VM thread.
{
// 4945125 The vm thread comes to a safepoint during exit.
// GC vm_operations can get caught at the safepoint, and the
// heap is unparseable if they are caught. Grab the Heap_lock
// to prevent this. The GC vm_operations will not be able to
// queue until after the vm thread is dead. After this point,
// we'll never emerge out of the safepoint before the VM exits.
MutexLocker ml(Heap_lock);
VMThread::wait_for_vm_thread_exit();
So this call is a problem:
src/hotspot/share/runtime/vmThread.cpp:
void VMThread::wait_for_vm_thread_exit() {
{ MutexLocker mu(VMOperationQueue_lock);