Search in sources :

Example 1 with MonitorNode

use of com.ibm.jvm.dtfjview.commands.helpers.MonitorNode in project openj9 by eclipse.

the class DeadlockCommand method doCommand.

public void doCommand() {
    SortedMap monitorNodes = new TreeMap();
    JavaRuntime jr = ctx.getRuntime();
    Iterator itMonitor = jr.getMonitors();
    int nodeListNum = 0;
    out.print("\n  deadlocks for runtime \n");
    // JVM dumps on Linux don't have all the image threads, so we now use JavaThreads
    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.println("exception encountered while getting monitor owner: " + Exceptions.getCorruptDataExceptionString());
            return;
        }
        if (null == owner) {
            // 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.println("exception encountered while getting owner's JavaObject: " + Exceptions.getCorruptDataExceptionString());
                return;
            }
            id = new Long(threadObject.getID().getAddress());
        }
        // Note: defect 133638, 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). Longer term the intention is to replace this
        // algorithm with the one used in javacore, but for now we carry on to see if we can
        // still find a deadlock, with some node(s) discarded.
        monitorNodes.put(id, node);
    }
    // Step 1.b
    // Add the JUC locks, technically to find all of them you need to walk the whole
    // heap. But the active ones can be found by walking the thread list and looking
    // at the blocking objects. (Any others aren't blocking any threads anyway so aren't
    // interesting.
    Iterator itThread = jr.getThreads();
    while (itThread.hasNext()) {
        try {
            Object o = itThread.next();
            if (!(o instanceof JavaThread)) {
                continue;
            }
            JavaThread jt = (JavaThread) o;
            JavaThread owner = null;
            Long id = null;
            if ((jt.getState() & JavaThread.STATE_PARKED) != 0) {
                JavaObject lock = jt.getBlockingObject();
                MonitorNode node = new JUCMonitorNode(lock, jr);
                try {
                    owner = Utils.getParkBlockerOwner(lock, jr);
                    if (owner == null) {
                        continue;
                    }
                } catch (MemoryAccessException e) {
                    out.println("exception encountered while getting monitor owner: " + Exceptions.getCorruptDataExceptionString());
                    return;
                }
                JavaObject threadObject;
                try {
                    threadObject = owner.getObject();
                } catch (CorruptDataException e) {
                    out.println("exception encountered while getting owner's JavaObject: " + Exceptions.getCorruptDataExceptionString());
                    return;
                }
                id = new Long(threadObject.getID().getAddress());
                monitorNodes.put(id, node);
            }
        } catch (CorruptDataException cde) {
            out.println("\nwarning, corrupt data encountered during scan for java.util.concurrent locks...");
        } catch (DataUnavailable du) {
            out.println("\nwarning, data unavailable encountered during scan for java.util.concurrent locks...");
        }
    }
    Iterator values = monitorNodes.values().iterator();
    // enter waiter, set that waiter's MonitorNode's waitingOn to m1.
    while (values.hasNext()) {
        MonitorNode currNode = (MonitorNode) values.next();
        Iterator itWaiters = currNode.getEnterWaiters();
        while (itWaiters.hasNext()) {
            Object o = itWaiters.next();
            if (!(o instanceof JavaThread)) {
                continue;
            }
            JavaThread waiter = (JavaThread) o;
            JavaObject threadObject;
            Long id = null;
            try {
                threadObject = waiter.getObject();
            } catch (CorruptDataException e) {
                out.println("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();
    while (values.hasNext()) {
        MonitorNode startNode = (MonitorNode) values.next();
        MonitorNode currNode = startNode;
        MonitorNode endNode;
        if (0 != startNode.visit) {
            continue;
        }
        while (true) {
            currNode.visit = visit;
            if (null == currNode.waitingOn) {
                currNode.deadlock = MonitorNode.NO_DEADLOCK;
                break;
            }
            if (isDeadlocked(currNode.waitingOn)) {
                // we've encountered a deadlocked node in the chain;
                // set branch deadlock for all nodes between startNode
                // and currNode
                endNode = currNode.waitingOn;
                currNode = startNode;
                NodeList branchList = null;
                while (currNode != endNode) {
                    if (null == branchList) {
                        branchList = new NodeList(currNode, nodeListNum++);
                    }
                    currNode.deadlock = MonitorNode.BRANCH_DEADLOCK;
                    currNode = currNode.waitingOn;
                    branchList.add(currNode);
                    if (currNode != endNode)
                        currNode.inList = branchList;
                }
                if (endNode.inList.isLoop()) {
                    lists.insertElementAt(branchList, lists.indexOf(endNode.inList));
                } else {
                    NodeList oldList = endNode.inList;
                    // FIXME: the below line will cause problems with at least
                    // one case that was not considered when attachOrSplit was
                    // coded: if a NodeList n1 has already been split and another
                    // NodeList n2 tries to attach to the end of n1, then n1 will
                    // allow n2 to attach to n1, while what n1 should really do is
                    // just return n2 and not allow n2 to attach to itself
                    NodeList split = endNode.inList.attachOrSplit(branchList, nodeListNum++);
                    if (null != split) {
                        lists.insertElementAt(split, lists.indexOf(oldList));
                        lists.insertElementAt(branchList, lists.indexOf(oldList));
                    }
                }
                break;
            }
            if (currNode.waitingOn.visit == visit) {
                // we've encountered a node in the same visit as the current
                // visit, ie. we've found a loop; first flag the whole loop
                // with a loop deadlock flag, then flag the rest of the nodes
                // in the chain with a branch deadlock
                endNode = currNode.waitingOn;
                currNode = endNode;
                NodeList loopList = new NodeList(currNode, nodeListNum++);
                lists.insertElementAt(loopList, 0);
                do {
                    currNode.deadlock = MonitorNode.LOOP_DEADLOCK;
                    currNode = currNode.waitingOn;
                    loopList.add(currNode);
                    currNode.inList = loopList;
                } while (currNode != endNode);
                currNode = startNode;
                NodeList branchList = null;
                while (currNode != endNode) {
                    if (null == branchList) {
                        branchList = new NodeList(currNode, nodeListNum++);
                        lists.insertElementAt(branchList, 0);
                    }
                    currNode.deadlock = MonitorNode.BRANCH_DEADLOCK;
                    currNode = currNode.waitingOn;
                    branchList.add(currNode);
                    if (currNode != endNode)
                        currNode.inList = branchList;
                }
                break;
            }
            currNode = currNode.waitingOn;
        }
        visit++;
    }
    if (lists.isEmpty()) {
        out.print("\n");
        out.print("\t no deadlocks detected");
        out.print("\n");
        return;
    }
    boolean lastListWasLoop = true;
    Iterator itList = lists.iterator();
    // Step 5. print the lists
    while (itList.hasNext()) {
        NodeList list = (NodeList) itList.next();
        if (list.isLoop()) {
            out.print("\n    deadlock loop:\n");
            lastListWasLoop = true;
        } else if (lastListWasLoop) {
            // && !list.isLoop()
            out.print("\n\n    deadlock branch(es):\n");
            lastListWasLoop = false;
        }
        out.print("\t  " + list.toString());
        out.print("\n");
    }
    out.print("\n");
}
Also used : JavaRuntime(com.ibm.dtfj.java.JavaRuntime) NodeList(com.ibm.jvm.dtfjview.commands.helpers.NodeList) CorruptDataException(com.ibm.dtfj.image.CorruptDataException) TreeMap(java.util.TreeMap) JUCMonitorNode(com.ibm.jvm.dtfjview.commands.helpers.JUCMonitorNode) JavaMonitor(com.ibm.dtfj.java.JavaMonitor) JUCMonitorNode(com.ibm.jvm.dtfjview.commands.helpers.JUCMonitorNode) MonitorNode(com.ibm.jvm.dtfjview.commands.helpers.MonitorNode) JavaObject(com.ibm.dtfj.java.JavaObject) SortedMap(java.util.SortedMap) Iterator(java.util.Iterator) JavaThread(com.ibm.dtfj.java.JavaThread) DataUnavailable(com.ibm.dtfj.image.DataUnavailable) JavaObject(com.ibm.dtfj.java.JavaObject) MemoryAccessException(com.ibm.dtfj.image.MemoryAccessException) Vector(java.util.Vector)

Aggregations

CorruptDataException (com.ibm.dtfj.image.CorruptDataException)1 DataUnavailable (com.ibm.dtfj.image.DataUnavailable)1 MemoryAccessException (com.ibm.dtfj.image.MemoryAccessException)1 JavaMonitor (com.ibm.dtfj.java.JavaMonitor)1 JavaObject (com.ibm.dtfj.java.JavaObject)1 JavaRuntime (com.ibm.dtfj.java.JavaRuntime)1 JavaThread (com.ibm.dtfj.java.JavaThread)1 JUCMonitorNode (com.ibm.jvm.dtfjview.commands.helpers.JUCMonitorNode)1 MonitorNode (com.ibm.jvm.dtfjview.commands.helpers.MonitorNode)1 NodeList (com.ibm.jvm.dtfjview.commands.helpers.NodeList)1 Iterator (java.util.Iterator)1 SortedMap (java.util.SortedMap)1 TreeMap (java.util.TreeMap)1 Vector (java.util.Vector)1