--- old/src/share/vm/prims/jvmtiEnvBase.cpp Tue Feb 26 15:23:12 2013 +++ new/src/share/vm/prims/jvmtiEnvBase.cpp Tue Feb 26 15:23:11 2013 @@ -997,13 +997,19 @@ // 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; --- old/src/share/vm/runtime/synchronizer.cpp Tue Feb 26 15:23:13 2013 +++ new/src/share/vm/runtime/synchronizer.cpp Tue Feb 26 15:23:13 2013 @@ -813,6 +813,7 @@ } if (owner != NULL) { + // owning_thread_from_monitor_owner() may also return NULL here return Threads::owning_thread_from_monitor_owner(owner, doLock); } --- old/src/share/vm/runtime/thread.cpp Tue Feb 26 15:23:14 2013 +++ new/src/share/vm/runtime/thread.cpp Tue Feb 26 15:23:14 2013 @@ -4285,7 +4285,9 @@ 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 @@ } } } - 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; } --- old/src/share/vm/services/threadService.cpp Tue Feb 26 15:23:15 2013 +++ new/src/share/vm/services/threadService.cpp Tue Feb 26 15:23:15 2013 @@ -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 @@ 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 @@ 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,