// Step 1. iterate over all monitors, creating a MonitorNode for each monitor that
// contains the monitor (JavaMonitor) and some parameters and adding that MonitorNode
// to a Hashtable, indexed by owner (JavaThread object address)
while (itMonitor.hasNext()) {
JavaMonitor monitor = (JavaMonitor)itMonitor.next();
MonitorNode node = new MonitorNode(monitor);
JavaThread owner = null;
Long id = null;
try {
owner = monitor.getOwner();
} catch (CorruptDataException e) {
out.error("exception encountered while getting monitor owner: " +
Exceptions.getCorruptDataExceptionString());
return;
}
if (null == owner) {
// A monitor with no owner cannot be involved in a deadlock, according to the
// algorithm used here anyway, because in order for a monitor to be in a deadlock,
// its owner must be in a deadlock or an owner somewhere down the chain of
// ownership must own the given monitor. Since there is no owner, we can't get
// the monitor's owner or the next monitor in a potential deadlock chain.
continue;
} else {
JavaObject threadObject;
try {
threadObject = owner.getObject();
} catch (CorruptDataException e) {
out.error("exception encountered while getting owner's JavaObject: " +
Exceptions.getCorruptDataExceptionString());
return;
}
id = new Long(threadObject.getID().getAddress());
}
// Note: we used to give up here with an error if there was already
// a monitor node in the table with the same key (thread). This is very common (a
// thread owning multiple monitors).
monitorNodes.put(id, node);
}
Iterator values = monitorNodes.values().iterator();
// Step 2. iterate over Hashtable and for every MonitorNode, iterate over monitor m1's
// enter waiters (JavaMonitor.getEnterWaiters()), which are JavaThreads, and for each
// enter waiter, set that waiter's MonitorNode's waitingOn to m1.
while (values.hasNext()) {
MonitorNode currNode = (MonitorNode)values.next();
JavaMonitor currMonitor = currNode.getMonitor();
Iterator itWaiters = currMonitor.getEnterWaiters().iterator();
while (itWaiters.hasNext()) {
JavaThread waiter = (JavaThread)itWaiters.next();
JavaObject threadObject;
Long id = null;
try {
threadObject = waiter.getObject();
} catch (CorruptDataException e) {
out.error("exception encountered while getting waiter's ImageThread: " +
Exceptions.getCorruptDataExceptionString());
return;
}
id = new Long(threadObject.getID().getAddress());
MonitorNode waiterNode = (MonitorNode)monitorNodes.get(id);
if (null != waiterNode) {
waiterNode.waitingOn = currNode;
}
}
}
values = monitorNodes.values().iterator();
int visit = 1;
Vector lists = new Vector();
// Step 3. iterate over Hashtable and for every MonitorNode m1:
// Step 3a. set a unique visit number, visit > 0 (visit++ would work)
// Step 3b. iterate over waitingOns, setting visit number, until a null
// waitingOn is reached (no deadlock), a deadlocked node is reached
// (m1 is part of a branch that joins a deadlock loop), or a node with
// the same visit is reached (m1 is part of a deadlock loop)
// Step 3c. if deadlock found, start at m1 and iterate over all
// waitingOns until a deadlocked node is found, setting deadlock
// (branch or loop, depending on result in 3b) along the way
// note: Step 4* are not laid out precisely as specified; the instructions
// listed for Step 4* are integrated into Step 3
// Step 4. for each MonitorNode m1 where inList == false and m1 is part
// of a deadlock loop *, create a new list and push it on the list
// stack right away:
// Step 4a. iterate over all enter waiters, setting inList to true at
// every MonitorNode
// Step 4b. if there are no enter waiters, terminate the current list
// Step 4c. if there is one enter waiter: if the enter waiter is the
// current list, stop; else continue creating the current list,
// iterating to that thread's MonitorNode
// Step 4d. if there is more than one enter waiter, continue creating
// current list and start a new list, pushing it on the list stack
// right away
while (values.hasNext())
{
MonitorNode startNode = (MonitorNode)values.next();
MonitorNode currNode = startNode;
MonitorNode endNode;
if (0 != startNode.visit)
{
continue;
}