Search in sources :

Example 1 with ThreadState

use of com.intellij.unscramble.ThreadState in project intellij-community by JetBrains.

the class ThreadDumpAction method buildThreadStates.

static List<ThreadState> buildThreadStates(VirtualMachineProxyImpl vmProxy) {
    final List<ThreadReference> threads = vmProxy.getVirtualMachine().allThreads();
    final List<ThreadState> result = new ArrayList<>();
    final Map<String, ThreadState> nameToThreadMap = new HashMap<>();
    // key 'waits_for' value
    final Map<String, String> waitingMap = new HashMap<>();
    for (ThreadReference threadReference : threads) {
        final StringBuilder buffer = new StringBuilder();
        boolean hasEmptyStack = true;
        final int threadStatus = threadReference.status();
        if (threadStatus == ThreadReference.THREAD_STATUS_ZOMBIE) {
            continue;
        }
        final String threadName = threadName(threadReference);
        final ThreadState threadState = new ThreadState(threadName, threadStatusToState(threadStatus));
        nameToThreadMap.put(threadName, threadState);
        result.add(threadState);
        threadState.setJavaThreadState(threadStatusToJavaThreadState(threadStatus));
        buffer.append("\"").append(threadName).append("\"");
        ReferenceType referenceType = threadReference.referenceType();
        if (referenceType != null) {
            //noinspection HardCodedStringLiteral
            Field daemon = referenceType.fieldByName("daemon");
            if (daemon != null) {
                Value value = threadReference.getValue(daemon);
                if (value instanceof BooleanValue && ((BooleanValue) value).booleanValue()) {
                    buffer.append(" ").append(DebuggerBundle.message("threads.export.attribute.label.daemon"));
                    threadState.setDaemon(true);
                }
            }
            //noinspection HardCodedStringLiteral
            Field priority = referenceType.fieldByName("priority");
            if (priority != null) {
                Value value = threadReference.getValue(priority);
                if (value instanceof IntegerValue) {
                    buffer.append(" ").append(DebuggerBundle.message("threads.export.attribute.label.priority", ((IntegerValue) value).intValue()));
                }
            }
            Field tid = referenceType.fieldByName("tid");
            if (tid != null) {
                Value value = threadReference.getValue(tid);
                if (value instanceof LongValue) {
                    buffer.append(" ").append(DebuggerBundle.message("threads.export.attribute.label.tid", Long.toHexString(((LongValue) value).longValue())));
                    buffer.append(" nid=NA");
                }
            }
        }
        //ThreadGroupReference groupReference = threadReference.threadGroup();
        //if (groupReference != null) {
        //  buffer.append(", ").append(DebuggerBundle.message("threads.export.attribute.label.group", groupReference.name()));
        //}
        final String state = threadState.getState();
        if (state != null) {
            buffer.append(" ").append(state);
        }
        buffer.append("\n  java.lang.Thread.State: ").append(threadState.getJavaThreadState());
        try {
            if (vmProxy.canGetOwnedMonitorInfo() && vmProxy.canGetMonitorInfo()) {
                List<ObjectReference> list = threadReference.ownedMonitors();
                for (ObjectReference reference : list) {
                    if (!vmProxy.canGetMonitorFrameInfo()) {
                        // java 5 and earlier
                        buffer.append("\n\t ").append(renderLockedObject(reference));
                    }
                    final List<ThreadReference> waiting = reference.waitingThreads();
                    for (ThreadReference thread : waiting) {
                        final String waitingThreadName = threadName(thread);
                        waitingMap.put(waitingThreadName, threadName);
                        buffer.append("\n\t ").append(DebuggerBundle.message("threads.export.attribute.label.blocks.thread", waitingThreadName));
                    }
                }
            }
            ObjectReference waitedMonitor = vmProxy.canGetCurrentContendedMonitor() ? threadReference.currentContendedMonitor() : null;
            if (waitedMonitor != null) {
                if (vmProxy.canGetMonitorInfo()) {
                    ThreadReference waitedMonitorOwner = waitedMonitor.owningThread();
                    if (waitedMonitorOwner != null) {
                        final String monitorOwningThreadName = threadName(waitedMonitorOwner);
                        waitingMap.put(threadName, monitorOwningThreadName);
                        buffer.append("\n\t ").append(DebuggerBundle.message("threads.export.attribute.label.waiting.for.thread", monitorOwningThreadName, renderObject(waitedMonitor)));
                    }
                }
            }
            final List<StackFrame> frames = threadReference.frames();
            hasEmptyStack = frames.size() == 0;
            final TIntObjectHashMap<List<ObjectReference>> lockedAt = new TIntObjectHashMap<>();
            if (vmProxy.canGetMonitorFrameInfo()) {
                for (MonitorInfo info : threadReference.ownedMonitorsAndFrames()) {
                    final int stackDepth = info.stackDepth();
                    List<ObjectReference> monitors;
                    if ((monitors = lockedAt.get(stackDepth)) == null) {
                        lockedAt.put(stackDepth, monitors = new SmartList<>());
                    }
                    monitors.add(info.monitor());
                }
            }
            for (int i = 0, framesSize = frames.size(); i < framesSize; i++) {
                final StackFrame stackFrame = frames.get(i);
                try {
                    final Location location = stackFrame.location();
                    buffer.append("\n\t  ").append(renderLocation(location));
                    final List<ObjectReference> monitors = lockedAt.get(i);
                    if (monitors != null) {
                        for (ObjectReference monitor : monitors) {
                            buffer.append("\n\t  - ").append(renderLockedObject(monitor));
                        }
                    }
                } catch (InvalidStackFrameException e) {
                    buffer.append("\n\t  Invalid stack frame: ").append(e.getMessage());
                }
            }
        } catch (IncompatibleThreadStateException e) {
            buffer.append("\n\t ").append(DebuggerBundle.message("threads.export.attribute.error.incompatible.state"));
        }
        threadState.setStackTrace(buffer.toString(), hasEmptyStack);
        ThreadDumpParser.inferThreadStateDetail(threadState);
    }
    for (String waiting : waitingMap.keySet()) {
        final ThreadState waitingThread = nameToThreadMap.get(waiting);
        final ThreadState awaitedThread = nameToThreadMap.get(waitingMap.get(waiting));
        if (waitingThread != null && awaitedThread != null) {
            //zombie
            awaitedThread.addWaitingThread(waitingThread);
        }
    }
    // detect simple deadlocks
    for (ThreadState thread : result) {
        for (ThreadState awaitingThread : thread.getAwaitingThreads()) {
            if (awaitingThread.isAwaitedBy(thread)) {
                thread.addDeadlockedThread(awaitingThread);
                awaitingThread.addDeadlockedThread(thread);
            }
        }
    }
    ThreadDumpParser.sortThreads(result);
    return result;
}
Also used : HashMap(java.util.HashMap) TIntObjectHashMap(gnu.trove.TIntObjectHashMap) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) SmartList(com.intellij.util.SmartList) ThreadState(com.intellij.unscramble.ThreadState) TIntObjectHashMap(gnu.trove.TIntObjectHashMap) SmartList(com.intellij.util.SmartList)

Aggregations

ThreadState (com.intellij.unscramble.ThreadState)1 SmartList (com.intellij.util.SmartList)1 TIntObjectHashMap (gnu.trove.TIntObjectHashMap)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 List (java.util.List)1