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; }
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC void markOopDesc::print_on(outputStream* st) const { if (is_marked()) { st->print(" marked(" INTPTR_FORMAT ")", value()); } else if (has_monitor()) { // have to check has_monitor() before is_locked() st->print(" monitor(" INTPTR_FORMAT ")=", value()); ObjectMonitor* mon = monitor(); if (mon == NULL) { st->print("NULL (this should never be seen!)"); } else { st->print("{count=" INTPTR_FORMAT ",waiters=" INTPTR_FORMAT ",recursions=" INTPTR_FORMAT ",owner=" INTPTR_FORMAT "}", mon->count(), mon->waiters(), mon->recursions(), p2i(mon->owner())); } } else if (is_locked()) { st->print(" locked(" INTPTR_FORMAT ")->", value()); if (is_neutral()) { st->print("is_neutral"); if (has_no_hash()) { st->print(" no_hash"); } else { st->print(" hash=" INTPTR_FORMAT, hash()); } st->print(" age=%d", age()); } else if (has_bias_pattern()) { st->print("is_biased"); JavaThread* jt = biased_locker(); st->print(" biased_locker=" INTPTR_FORMAT, p2i(jt)); } else { st->print("??"); } } else { assert(is_unlocked() || has_bias_pattern(), "just checking"); st->print("mark("); if (has_bias_pattern()) st->print("biased,"); st->print("hash %#lx,", hash()); st->print("age %d)", age()); } }
jvmtiError JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject object, jvmtiMonitorUsage* info_ptr) { HandleMark hm; Handle hobj; bool at_safepoint = SafepointSynchronize::is_at_safepoint(); // Check arguments { oop mirror = JNIHandles::resolve_external_guard(object); NULL_CHECK(mirror, JVMTI_ERROR_INVALID_OBJECT); NULL_CHECK(info_ptr, JVMTI_ERROR_NULL_POINTER); hobj = Handle(mirror); } JavaThread *owning_thread = NULL; ObjectMonitor *mon = NULL; jvmtiMonitorUsage ret = { NULL, 0, 0, NULL, 0, NULL }; uint32_t debug_bits = 0; // first derive the object's owner and entry_count (if any) { // Revoke any biases before querying the mark word if (SafepointSynchronize::is_at_safepoint()) { BiasedLocking::revoke_at_safepoint(hobj); } else { BiasedLocking::revoke_and_rebias(hobj, false, calling_thread); } address owner = NULL; { markOop mark = hobj()->mark(); if (!mark->has_monitor()) { // this object has a lightweight monitor if (mark->has_locker()) { owner = (address)mark->locker(); // save the address of the Lock word } // implied else: no owner } else { // this object has a heavyweight monitor mon = mark->monitor(); // The owner field of a heavyweight monitor may be NULL for no // owner, a JavaThread * or it may still be the address of the // Lock word in a JavaThread's stack. A monitor can be inflated // by a non-owning JavaThread, but only the owning JavaThread // can change the owner field from the Lock word to the // JavaThread * and it may not have done that yet. owner = (address)mon->owner(); } } if (owner != NULL) { // This monitor is owned so we have to find the owning JavaThread. // Since owning_thread_from_monitor_owner() grabs a lock, GC can // move our object at this point. However, our owner value is safe // since it is either the Lock word on a stack or a JavaThread *. owning_thread = Threads::owning_thread_from_monitor_owner(owner, !at_safepoint); // Cannot assume (owning_thread != NULL) here because this function // may not have been called at a safepoint and the owning_thread // might not be suspended. if (owning_thread != NULL) { // The monitor's owner either has to be the current thread, at safepoint // or it has to be suspended. Any of these conditions will prevent both // contending and waiting threads from modifying the state of // the monitor. if (!at_safepoint && !JvmtiEnv::is_thread_fully_suspended(owning_thread, true, &debug_bits)) { // Don't worry! This return of JVMTI_ERROR_THREAD_NOT_SUSPENDED // will not make it back to the JVM/TI agent. The error code will // get intercepted in JvmtiEnv::GetObjectMonitorUsage() which // will retry the call via a VM_GetObjectMonitorUsage VM op. return JVMTI_ERROR_THREAD_NOT_SUSPENDED; } HandleMark hm; Handle th(owning_thread->threadObj()); ret.owner = (jthread)jni_reference(calling_thread, th); } // implied else: no owner } if (owning_thread != NULL) { // monitor is owned // The recursions field of a monitor does not reflect recursions // as lightweight locks before inflating the monitor are not included. // We have to count the number of recursive monitor entries the hard way. // We pass a handle to survive any GCs along the way. ResourceMark rm; ret.entry_count = count_locked_objects(owning_thread, hobj); } // implied else: entry_count == 0 } jint nWant, nWait; if (mon != NULL) { // this object has a heavyweight monitor nWant = mon->contentions(); // # of threads contending for monitor nWait = mon->waiters(); // # of threads in Object.wait() ret.waiter_count = nWant + nWait; ret.notify_waiter_count = nWait; } else { // this object has a lightweight monitor ret.waiter_count = 0; ret.notify_waiter_count = 0; } // Allocate memory for heavyweight and lightweight monitor. jvmtiError err; err = allocate(ret.waiter_count * sizeof(jthread *), (unsigned char**)&ret.waiters); if (err != JVMTI_ERROR_NONE) { return err; } err = allocate(ret.notify_waiter_count * sizeof(jthread *), (unsigned char**)&ret.notify_waiters); if (err != JVMTI_ERROR_NONE) { deallocate((unsigned char*)ret.waiters); return err; } // now derive the rest of the fields if (mon != NULL) { // this object has a heavyweight monitor // Number of waiters may actually be less than the waiter count. // So NULL out memory so that unused memory will be NULL. memset(ret.waiters, 0, ret.waiter_count * sizeof(jthread *)); memset(ret.notify_waiters, 0, ret.notify_waiter_count * sizeof(jthread *)); if (ret.waiter_count > 0) { // we have contending and/or waiting threads HandleMark hm; if (nWant > 0) { // we have contending threads ResourceMark rm; // get_pending_threads returns only java thread so we do not need to // check for non java threads. GrowableArray<JavaThread*>* wantList = Threads::get_pending_threads( nWant, (address)mon, !at_safepoint); if (wantList->length() < nWant) { // robustness: the pending list has gotten smaller nWant = wantList->length(); } for (int i = 0; i < nWant; i++) { JavaThread *pending_thread = wantList->at(i); // If the monitor has no owner, then a non-suspended contending // thread could potentially change the state of the monitor by // entering it. The JVM/TI spec doesn't allow this. if (owning_thread == NULL && !at_safepoint & !JvmtiEnv::is_thread_fully_suspended(pending_thread, true, &debug_bits)) { if (ret.owner != NULL) { destroy_jni_reference(calling_thread, ret.owner); } for (int j = 0; j < i; j++) { destroy_jni_reference(calling_thread, ret.waiters[j]); } deallocate((unsigned char*)ret.waiters); deallocate((unsigned char*)ret.notify_waiters); return JVMTI_ERROR_THREAD_NOT_SUSPENDED; } Handle th(pending_thread->threadObj()); ret.waiters[i] = (jthread)jni_reference(calling_thread, th); } } if (nWait > 0) { // we have threads in Object.wait() int offset = nWant; // add after any contending threads ObjectWaiter *waiter = mon->first_waiter(); for (int i = 0, j = 0; i < nWait; i++) { if (waiter == NULL) { // robustness: the waiting list has gotten smaller nWait = j; break; } Thread *t = mon->thread_of_waiter(waiter); if (t != NULL && t->is_Java_thread()) { JavaThread *wjava_thread = (JavaThread *)t; // If the thread was found on the ObjectWaiter list, then // it has not been notified. This thread can't change the // state of the monitor so it doesn't need to be suspended. Handle th(wjava_thread->threadObj()); ret.waiters[offset + j] = (jthread)jni_reference(calling_thread, th); ret.notify_waiters[j++] = (jthread)jni_reference(calling_thread, th); } waiter = mon->next_waiter(waiter); } } } // Adjust count. nWant and nWait count values may be less than original. ret.waiter_count = nWant + nWait; ret.notify_waiter_count = nWait; } else { // this object has a lightweight monitor and we have nothing more // to do here because the defaults are just fine. } // we don't update return parameter unless everything worked *info_ptr = ret; return JVMTI_ERROR_NONE; }
// 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; }