diff --git a/src/share/vm/prims/jvmtiEnvBase.cpp b/src/share/vm/prims/jvmtiEnvBase.cpp index 56387634179bf431ea84c107424f782fbcb05e45..597d7a164dc514bd74c6ba6b8fbdb81a6479d2ab 100644 --- a/src/share/vm/prims/jvmtiEnvBase.cpp +++ b/src/share/vm/prims/jvmtiEnvBase.cpp @@ -997,13 +997,19 @@ JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject objec // 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); - assert(owning_thread != NULL, "sanity check"); - if (owning_thread != NULL) { // robustness + // 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; diff --git a/src/share/vm/runtime/synchronizer.cpp b/src/share/vm/runtime/synchronizer.cpp index bdf416275dccd0040a26a4d5608d3df3ecc87474..bff39625ed4d96d21ed4b685d4720604f6db2779 100644 --- a/src/share/vm/runtime/synchronizer.cpp +++ b/src/share/vm/runtime/synchronizer.cpp @@ -813,6 +813,7 @@ JavaThread* ObjectSynchronizer::get_lock_owner(Handle h_obj, bool doLock) { } if (owner != NULL) { + // owning_thread_from_monitor_owner() may also return NULL here return Threads::owning_thread_from_monitor_owner(owner, doLock); } diff --git a/src/share/vm/runtime/thread.cpp b/src/share/vm/runtime/thread.cpp index e0cf75b03f20c9e5562291ef29a604e7033c8df7..cb883c5d8215dce3a7ff0f32c7e656bd43746bde 100644 --- a/src/share/vm/runtime/thread.cpp +++ b/src/share/vm/runtime/thread.cpp @@ -4285,7 +4285,9 @@ JavaThread *Threads::owning_thread_from_monitor_owner(address owner, bool doLock if (owner == (address)p) return p; } } - assert(UseHeavyMonitors == false, "Did not find owning Java thread with UseHeavyMonitors enabled"); + // Cannot assert on lack of success here since this function may be + // used by code that is trying to report useful problem information + // like deadlock detection. if (UseHeavyMonitors) return NULL; // @@ -4303,7 +4305,7 @@ JavaThread *Threads::owning_thread_from_monitor_owner(address owner, bool doLock } } } - assert(the_owner != NULL, "Did not find owning Java thread for lock word address"); + // cannot assert on lack of success here; see above comment return the_owner; } diff --git a/src/share/vm/services/threadService.cpp b/src/share/vm/services/threadService.cpp index b1c92c0b1101f855a3a4d6f3b498c6620ad29727..03289c7e9ac2499a4a0e5a5f91477a8dd1c84f6c 100644 --- a/src/share/vm/services/threadService.cpp +++ b/src/share/vm/services/threadService.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -327,8 +327,28 @@ DeadlockCycle* ThreadService::find_deadlocks_at_safepoint(bool concurrent_locks) while (waitingToLockMonitor != NULL || waitingToLockBlocker != NULL) { cycle->add_thread(currentThread); if (waitingToLockMonitor != NULL) { - currentThread = Threads::owning_thread_from_monitor_owner((address)waitingToLockMonitor->owner(), - false /* no locking needed */); + currentThread = Threads::owning_thread_from_monitor_owner( + (address)waitingToLockMonitor->owner(), + 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())) { @@ -841,7 +861,17 @@ void DeadlockCycle::print_on(outputStream* st) const { owner_desc = " (JVMTI raw monitor),\n which is held by"; } currentThread = Threads::owning_thread_from_monitor_owner( - (address)waitingToLockMonitor->owner(), false /* no locking needed */); + (address)waitingToLockMonitor->owner(), + false /* no locking needed */); + if (currentThread == NULL) { + // The deadlock was detected 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. + st->print("%s UNKNOWN_owner_addr=" PTR_FORMAT, owner_desc, + (address)waitingToLockMonitor->owner()); + continue; + } } else { st->print(" waiting for ownable synchronizer " INTPTR_FORMAT ", (a %s)", (address)waitingToLockBlocker,