private void commandKill(StringTokenizer t) throws NoSessionException { // ### Should change the way in which thread ids and threadgroup names // ### are distinguished. if (!t.hasMoreTokens()) { env.error("Usage: kill <threadgroup name> or <thread id>"); return; } while (t.hasMoreTokens()) { String idToken = t.nextToken(); ThreadReference thread = findThread(idToken); if (thread != null) { runtime.stopThread(thread); env.notice("Thread " + thread.name() + " killed."); return; } else { /* Check for threadgroup name, NOT skipping "system". */ // ### Should skip "system"? Classic 'jdb' does this. // ### Should deal with possible non-uniqueness of threadgroup names. ThreadGroupIterator itg = allThreadGroups(); while (itg.hasNext()) { ThreadGroupReference tg = itg.nextThreadGroup(); if (tg.name().equals(idToken)) { ThreadIterator it = new ThreadIterator(tg); while (it.hasNext()) { runtime.stopThread(it.nextThread()); } env.notice("Threadgroup " + tg.name() + "killed."); return; } } env.failure("\"" + idToken + "\" is not a valid threadgroup or id."); } } }
private int printThreadGroup(OutputSink out, ThreadGroupReference tg, int iThread) { out.println("Group " + tg.name() + ":"); List<ThreadReference> tlist = tg.threads(); int maxId = 0; int maxName = 0; for (int i = 0; i < tlist.size(); i++) { ThreadReference thr = tlist.get(i); int len = Utils.description(thr).length(); if (len > maxId) { maxId = len; } String name = thr.name(); int iDot = name.lastIndexOf('.'); if (iDot >= 0 && name.length() > iDot) { name = name.substring(iDot + 1); } if (name.length() > maxName) { maxName = name.length(); } } String maxNumString = String.valueOf(iThread + tlist.size()); int maxNumDigits = maxNumString.length(); for (int i = 0; i < tlist.size(); i++) { ThreadReference thr = tlist.get(i); char buf[] = new char[80]; for (int j = 0; j < 79; j++) { buf[j] = ' '; } buf[79] = '\0'; StringBuffer sbOut = new StringBuffer(); sbOut.append(buf); // Right-justify the thread number at start of output string String numString = String.valueOf(iThread + i + 1); sbOut.insert(maxNumDigits - numString.length(), numString); sbOut.insert(maxNumDigits, "."); int iBuf = maxNumDigits + 2; sbOut.insert(iBuf, Utils.description(thr)); iBuf += maxId + 1; String name = thr.name(); int iDot = name.lastIndexOf('.'); if (iDot >= 0 && name.length() > iDot) { name = name.substring(iDot + 1); } sbOut.insert(iBuf, name); iBuf += maxName + 1; sbOut.insert(iBuf, Utils.getStatus(thr)); sbOut.setLength(79); out.println(sbOut.toString()); } for (ThreadGroupReference tg0 : tg.threadGroups()) { if (!tg.equals(tg0)) { // TODO ref mgt iThread += printThreadGroup(out, tg0, iThread + tlist.size()); } } return tlist.size(); }
private void commandThreadGroups() throws NoSessionException { ThreadGroupIterator it = allThreadGroups(); int cnt = 0; OutputSink out = env.getOutputSink(); while (it.hasNext()) { ThreadGroupReference tg = it.nextThreadGroup(); ++cnt; out.println("" + cnt + ". " + Utils.description(tg) + " " + tg.name()); } out.show(); }
private ThreadGroupReference findThreadGroup(String name) throws NoSessionException { // ### Issue: Uniqueness of thread group names is not enforced. ThreadGroupIterator tgi = allThreadGroups(); while (tgi.hasNext()) { ThreadGroupReference tg = tgi.nextThreadGroup(); if (tg.name().equals(name)) { return tg; } } return null; }
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; }