8007476: assert(the_owner != NULL) failed: Did not find owning Java thread for lock word address
Summary: Make deadlock detection a little more robust in the case of being unable to find the JavaThread associated with an object lock.
Reviewed-by: sla, acorn
--- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp Wed Feb 27 16:40:30 2013 +0000
+++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp Wed Feb 27 15:00:30 2013 -0800
@@ -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;
--- a/hotspot/src/share/vm/runtime/synchronizer.cpp Wed Feb 27 16:40:30 2013 +0000
+++ b/hotspot/src/share/vm/runtime/synchronizer.cpp Wed Feb 27 15:00:30 2013 -0800
@@ -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);
}
--- a/hotspot/src/share/vm/runtime/thread.cpp Wed Feb 27 16:40:30 2013 +0000
+++ b/hotspot/src/share/vm/runtime/thread.cpp Wed Feb 27 15:00:30 2013 -0800
@@ -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;
}
--- a/hotspot/src/share/vm/services/threadService.cpp Wed Feb 27 16:40:30 2013 +0000
+++ b/hotspot/src/share/vm/services/threadService.cpp Wed Feb 27 15:00:30 2013 -0800
@@ -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,