void DeadlockCycle::print_on(outputStream* st) const { st->cr(); st->print_cr("Found one Java-level deadlock:"); st->print("============================="); JavaThread* currentThread; ObjectMonitor* waitingToLockMonitor; oop waitingToLockBlocker; int len = _threads->length(); for (int i = 0; i < len; i++) { currentThread = _threads->at(i); waitingToLockMonitor = (ObjectMonitor*)currentThread->current_pending_monitor(); waitingToLockBlocker = currentThread->current_park_blocker(); st->cr(); st->print_cr("\"%s\":", currentThread->get_thread_name()); const char* owner_desc = ",\n which is held by"; if (waitingToLockMonitor != NULL) { st->print(" waiting to lock monitor " INTPTR_FORMAT, waitingToLockMonitor); oop obj = (oop)waitingToLockMonitor->object(); if (obj != NULL) { st->print(" (object "INTPTR_FORMAT ", a %s)", (address)obj, (instanceKlass::cast(obj->klass()))->external_name()); if (!currentThread->current_pending_monitor_is_from_java()) { owner_desc = "\n in JNI, which is held by"; } } else { // No Java object associated - a JVMTI raw monitor owner_desc = " (JVMTI raw monitor),\n which is held by"; } currentThread = Threads::owning_thread_from_monitor_owner( (address)waitingToLockMonitor->owner(), false /* no locking needed */); } else { st->print(" waiting for ownable synchronizer " INTPTR_FORMAT ", (a %s)", (address)waitingToLockBlocker, (instanceKlass::cast(waitingToLockBlocker->klass()))->external_name()); assert(waitingToLockBlocker->is_a(SystemDictionary::abstract_ownable_synchronizer_klass()), "Must be an AbstractOwnableSynchronizer"); oop ownerObj = java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(waitingToLockBlocker); currentThread = java_lang_Thread::thread(ownerObj); } st->print("%s \"%s\"", owner_desc, currentThread->get_thread_name()); } st->cr(); st->cr(); // Print stack traces bool oldJavaMonitorsInStackTrace = JavaMonitorsInStackTrace; JavaMonitorsInStackTrace = true; st->print_cr("Java stack information for the threads listed above:"); st->print_cr("==================================================="); for (int j = 0; j < len; j++) { currentThread = _threads->at(j); st->print_cr("\"%s\":", currentThread->get_thread_name()); currentThread->print_stack_on(st); } JavaMonitorsInStackTrace = oldJavaMonitorsInStackTrace; }
// Find deadlocks involving object monitors and concurrent locks if concurrent_locks is true DeadlockCycle* ThreadService::find_deadlocks_at_safepoint(bool concurrent_locks) { // This code was modified from the original Threads::find_deadlocks code. int globalDfn = 0, thisDfn; ObjectMonitor* waitingToLockMonitor = NULL; oop waitingToLockBlocker = NULL; bool blocked_on_monitor = false; JavaThread *currentThread, *previousThread; int num_deadlocks = 0; for (JavaThread* p = Threads::first(); p != NULL; p = p->next()) { // Initialize the depth-first-number p->set_depth_first_number(-1); } DeadlockCycle* deadlocks = NULL; DeadlockCycle* last = NULL; DeadlockCycle* cycle = new DeadlockCycle(); for (JavaThread* jt = Threads::first(); jt != NULL; jt = jt->next()) { if (jt->depth_first_number() >= 0) { // this thread was already visited continue; } thisDfn = globalDfn; jt->set_depth_first_number(globalDfn++); previousThread = jt; currentThread = jt; cycle->reset(); // 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 = (ObjectMonitor*)jt->current_pending_monitor(); if (concurrent_locks) { waitingToLockBlocker = jt->current_park_blocker(); } while (waitingToLockMonitor != NULL || waitingToLockBlocker != NULL) { cycle->add_thread(currentThread); if (waitingToLockMonitor != NULL) { address currentOwner = (address)waitingToLockMonitor->owner(); if (currentOwner != NULL) { currentThread = Threads::owning_thread_from_monitor_owner( currentOwner, false /* no locking needed */); if (currentThread == NULL) { // This function is called at a safepoint so the JavaThread // that owns waitingToLockMonitor should be findable, but // if it is not findable, then the previous currentThread is // blocked permanently. We record this as a deadlock. num_deadlocks++; cycle->set_deadlock(true); // add this cycle to the deadlocks list if (deadlocks == NULL) { deadlocks = cycle; } else { last->set_next(cycle); } last = cycle; cycle = new DeadlockCycle(); break; } } } else { if (concurrent_locks) { if (waitingToLockBlocker->is_a(SystemDictionary::abstract_ownable_synchronizer_klass())) { oop threadObj = java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(waitingToLockBlocker); currentThread = threadObj != NULL ? java_lang_Thread::thread(threadObj) : NULL; } else { currentThread = NULL; } } } if (currentThread == NULL) { // No dependency on another thread break; } if (currentThread->depth_first_number() < 0) { // First visit to this thread currentThread->set_depth_first_number(globalDfn++); } else if (currentThread->depth_first_number() < thisDfn) { // Thread already visited, and not on a (new) cycle break; } else if (currentThread == previousThread) { // Self-loop, ignore break; } else { // We have a (new) cycle num_deadlocks++; cycle->set_deadlock(true); // add this cycle to the deadlocks list if (deadlocks == NULL) { deadlocks = cycle; } else { last->set_next(cycle); } last = cycle; cycle = new DeadlockCycle(); break; } previousThread = currentThread; waitingToLockMonitor = (ObjectMonitor*)currentThread->current_pending_monitor(); if (concurrent_locks) { waitingToLockBlocker = currentThread->current_park_blocker(); } } } delete cycle; return deadlocks; }