--- old/src/hotspot/share/services/threadService.cpp 2020-02-03 17:40:00.000000000 -0500 +++ new/src/hotspot/share/services/threadService.cpp 2020-02-03 17:39:59.000000000 -0500 @@ -208,7 +208,12 @@ assert(thread != NULL, "should be non-NULL"); debug_only(Thread::check_for_dangling_thread_pointer(thread);) - ObjectMonitor *wait_obj = thread->current_waiting_monitor(); + // This function can be called on a target JavaThread that is not + // the caller and we are not at a safepoint. This ObjectMonitorHandle + // keeps the ObjectMonitor from being async deflated so the object + // reference we fetch remains non-NULL. + ObjectMonitorHandle omh; + ObjectMonitor *wait_obj = thread->current_waiting_monitor(&omh); oop obj = NULL; if (wait_obj != NULL) { @@ -216,7 +221,7 @@ obj = (oop) wait_obj->object(); assert(obj != NULL, "Object.wait() should have an object"); } else { - ObjectMonitor *enter_obj = thread->current_pending_monitor(); + ObjectMonitor *enter_obj = thread->current_pending_monitor(&omh); if (enter_obj != NULL) { // thread is trying to enter() an ObjectMonitor. obj = (oop) enter_obj->object(); @@ -362,6 +367,9 @@ // This code was modified from the original Threads::find_deadlocks code. int globalDfn = 0, thisDfn; + // This code is called at a safepoint so this ObjectMonitorHandle + // is not strictly necessary. + ObjectMonitorHandle omh; ObjectMonitor* waitingToLockMonitor = NULL; JvmtiRawMonitor* waitingToLockRawMonitor = NULL; oop waitingToLockBlocker = NULL; @@ -391,10 +399,15 @@ cycle->reset(); + if (waitingToLockMonitor != NULL) { + // Done with the current waitingToLockMonitor value so release + // the ObjectMonitorHandle manually before we use it again: + omh.unset_om_ptr(); + } // When there is a deadlock, all the monitors involved in the dependency // cycle must be contended and heavyweight. So we only care about the // heavyweight monitor a thread is waiting to lock. - waitingToLockMonitor = jt->current_pending_monitor(); + waitingToLockMonitor = jt->current_pending_monitor(&omh); // JVM TI raw monitors can also be involved in deadlocks, and we can be // waiting to lock both a raw monitor and ObjectMonitor at the same time. // It isn't clear how to make deadlock detection work correctly if that @@ -485,7 +498,12 @@ break; } previousThread = currentThread; - waitingToLockMonitor = (ObjectMonitor*)currentThread->current_pending_monitor(); + if (waitingToLockMonitor != NULL) { + // Done with the current waitingToLockMonitor value so release + // the ObjectMonitorHandle manually before we use it again: + omh.unset_om_ptr(); + } + waitingToLockMonitor = (ObjectMonitor*)currentThread->current_pending_monitor(&omh); if (concurrent_locks) { waitingToLockBlocker = currentThread->current_park_blocker(); } @@ -967,13 +985,15 @@ st->print("============================="); JavaThread* currentThread; - ObjectMonitor* waitingToLockMonitor; JvmtiRawMonitor* waitingToLockRawMonitor; oop waitingToLockBlocker; int len = _threads->length(); for (int i = 0; i < len; i++) { currentThread = _threads->at(i); - waitingToLockMonitor = currentThread->current_pending_monitor(); + // This code is called at a safepoint so this ObjectMonitorHandle + // is not strictly necessary. + ObjectMonitorHandle omh; + ObjectMonitor* waitingToLockMonitor = currentThread->current_pending_monitor(&omh); waitingToLockRawMonitor = currentThread->current_pending_raw_monitor(); waitingToLockBlocker = currentThread->current_park_blocker(); st->cr();