private static List<ThreadState> buildThreadStates(VirtualMachineProxyImpl vmProxy) { final List<ThreadReference> threads = vmProxy.getVirtualMachine().allThreads(); final List<ThreadState> result = new ArrayList<ThreadState>(); final Map<String, ThreadState> nameToThreadMap = new HashMap<String, ThreadState>(); final Map<String, String> waitingMap = new HashMap<String, String>(); // key 'waits_for' value for (ThreadReference threadReference : threads) { final StringBuilder buffer = new StringBuilder(); boolean hasEmptyStack = true; final String threadName = threadName(threadReference); final int threadStatus = threadReference.status(); final ThreadState threadState = new ThreadState(threadName, threadStatusToState(threadStatus)); nameToThreadMap.put(threadName, threadState); result.add(threadState); threadState.setJavaThreadState(threadStatusToJavaThreadState(threadStatus)); buffer.append(threadName); 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")); } } //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())); } } } ThreadGroupReference groupReference = threadReference.threadGroup(); if (groupReference != null) { buffer .append(", ") .append( DebuggerBundle.message( "threads.export.attribute.label.group", groupReference.name())); } buffer .append(", ") .append( DebuggerBundle.message( "threads.export.attribute.label.status", threadState.getState())); 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) { 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)); } } } final List<StackFrame> frames = threadReference.frames(); hasEmptyStack = frames.size() == 0; for (StackFrame stackFrame : frames) { final Location location = stackFrame.location(); buffer.append("\n\t ").append(renderLocation(location)); } } 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)); 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; }