public static CharSequence getThreadStats( boolean lockedMonitors, boolean lockedSynchronizers, boolean stackTrace) { StringBuilder list = new StringBuilder(); int threadCount = threadMXbean.getThreadCount(); int daemonCount = threadMXbean.getThreadCount(); int nonDaemonCount = threadCount - daemonCount; int peakCount = threadMXbean.getPeakThreadCount(); long totalCount = threadMXbean.getTotalStartedThreadCount(); list.append("Live: .................... ").append(threadCount).append(" threads").append("\n"); list.append(" Non-Daemon: ......... ") .append(nonDaemonCount) .append(" threads") .append("\n"); list.append(" Daemon: ............. ").append(daemonCount).append(" threads").append("\n"); list.append("Peak: .................... ").append(peakCount).append(" threads").append("\n"); list.append("Total started: ........... ").append(totalCount).append(" threads").append("\n"); list.append("=================================================").append("\n"); for (ThreadInfo info : threadMXbean.dumpAllThreads(lockedMonitors, lockedSynchronizers)) { list.append("Thread #") .append(info.getThreadId()) .append(" (") .append(info.getThreadName()) .append(")") .append("\n"); list.append("=================================================\n"); list.append("\tgetThreadState: ...... ").append(info.getThreadState()).append("\n"); list.append("\tgetWaitedTime: ....... ").append(info.getWaitedTime()).append("\n"); list.append("\tgetBlockedTime: ...... ").append(info.getBlockedTime()).append("\n"); for (MonitorInfo monitorInfo : info.getLockedMonitors()) { list.append("\tLocked monitor: ....... ").append(monitorInfo).append("\n"); list.append("\t\t[") .append(monitorInfo.getLockedStackDepth()) .append(".]: at ") .append(monitorInfo.getLockedStackFrame()) .append("\n"); } for (LockInfo lockInfo : info.getLockedSynchronizers()) { list.append("\tLocked synchronizer: ...").append(lockInfo).append("\n"); } if (stackTrace) { list.append("\tgetStackTace: ..........\n"); for (StackTraceElement trace : info.getStackTrace()) list.append("\t\tat ").append(trace).append("\n"); } list.append("=================================================\n"); } return list; }
private static void printThreadInfo(ThreadInfo threadInfo, StringBuilder threadDump) { // Print thread information printThread(threadInfo, threadDump); // print stack trace with locks StackTraceElement[] stacktrace = threadInfo.getStackTrace(); MonitorInfo[] monitors = threadInfo.getLockedMonitors(); for (int i = 0; i < stacktrace.length; i++) { StackTraceElement ste = stacktrace[i]; threadDump.append(INDENT + "at " + ste.toString()); threadDump.append("\n"); for (int j = 1; j < monitors.length; j++) { MonitorInfo mi = monitors[j]; if (mi.getLockedStackDepth() == i) { threadDump.append(INDENT + " - locked " + mi); threadDump.append("\n"); } } } threadDump.append("\n"); }
/** * Formats the thread dump for one thread. * * @param ti the ThreadInfo describing the thread * @return the formatted thread dump */ private static String getThreadDump(ThreadInfo ti) { StringBuilder sb = new StringBuilder(getThreadDumpHeader(ti)); for (LockInfo li : ti.getLockedSynchronizers()) { sb.append(INDENT2 + "locks " + li.toString() + CRLF); } boolean start = true; StackTraceElement[] stes = ti.getStackTrace(); Object[] monitorDepths = new Object[stes.length]; MonitorInfo[] mis = ti.getLockedMonitors(); for (int i = 0; i < mis.length; i++) { monitorDepths[mis[i].getLockedStackDepth()] = mis[i]; } for (int i = 0; i < stes.length; i++) { StackTraceElement ste = stes[i]; sb.append(INDENT2 + "at " + ste.toString() + CRLF); if (start) { if (ti.getLockName() != null) { sb.append(INDENT2 + "- waiting on (a " + ti.getLockName() + ")"); if (ti.getLockOwnerName() != null) { sb.append(" owned by " + ti.getLockOwnerName() + " Id=" + ti.getLockOwnerId()); } sb.append(CRLF); } start = false; } if (monitorDepths[i] != null) { MonitorInfo mi = (MonitorInfo) monitorDepths[i]; sb.append( INDENT2 + "- locked (a " + mi.toString() + ")" + " index " + mi.getLockedStackDepth() + " frame " + mi.getLockedStackFrame().toString()); sb.append(CRLF); } } return sb.toString(); }
void checkThreadInfo(ThreadInfo info) { if (!getName().equals(info.getThreadName())) { throw new RuntimeException( "Name: " + info.getThreadName() + " not matched. Expected: " + getName()); } MonitorInfo[] monitors = info.getLockedMonitors(); if (monitors.length != OWNED_MONITORS) { throw new RuntimeException( "Number of locked monitors = " + monitors.length + " not matched. Expected: " + OWNED_MONITORS); } MonitorInfo m = monitors[0]; StackTraceElement ste = m.getLockedStackFrame(); int depth = m.getLockedStackDepth(); StackTraceElement[] stacktrace = info.getStackTrace(); if (!ste.equals(stacktrace[depth])) { System.out.println("LockedStackFrame:- " + ste); System.out.println("StackTrace at " + depth + " :-" + stacktrace[depth]); throw new RuntimeException( "LockedStackFrame does not match " + "stack frame in ThreadInfo.getStackTrace"); } String className = lock.getClass().getName(); int hcode = System.identityHashCode(lock); if (!className.equals(m.getClassName()) || hcode != m.getIdentityHashCode() || !m.getLockedStackFrame().getMethodName().equals("run")) { System.out.println(info); throw new RuntimeException("MonitorInfo " + m + " doesn't match."); } LockInfo[] syncs = info.getLockedSynchronizers(); if (syncs.length != OWNED_SYNCS) { throw new RuntimeException( "Number of locked syncs = " + syncs.length + " not matched. Expected: " + OWNED_SYNCS); } AbstractOwnableSynchronizer s = mutex.getSync(); String lockName = s.getClass().getName(); hcode = System.identityHashCode(s); if (!lockName.equals(syncs[0].getClassName())) { throw new RuntimeException( "LockInfo : " + syncs[0] + " class name not matched. Expected: " + lockName); } if (hcode != syncs[0].getIdentityHashCode()) { throw new RuntimeException( "LockInfo: " + syncs[0] + " IdentityHashCode not matched. Expected: " + hcode); } LockInfo li = info.getLockInfo(); if (li == null) { throw new RuntimeException("Expected non-null LockInfo"); } }
// ThreadInfo.toString() truncates the stack trace by first 8, so needed my own version @IgnoreJRERequirement public static String dumpThreadInfo(ThreadInfo ti) { StringBuilder sb = new StringBuilder( "\"" + ti.getThreadName() + "\"" + " Id=" + ti.getThreadId() + " " + ti.getThreadState()); if (ti.getLockName() != null) { sb.append(" on " + ti.getLockName()); } if (ti.getLockOwnerName() != null) { sb.append(" owned by \"" + ti.getLockOwnerName() + "\" Id=" + ti.getLockOwnerId()); } if (ti.isSuspended()) { sb.append(" (suspended)"); } if (ti.isInNative()) { sb.append(" (in native)"); } sb.append('\n'); StackTraceElement[] stackTrace = ti.getStackTrace(); for (int i = 0; i < stackTrace.length; i++) { StackTraceElement ste = stackTrace[i]; sb.append("\tat " + ste.toString()); sb.append('\n'); if (i == 0 && ti.getLockInfo() != null) { Thread.State ts = ti.getThreadState(); switch (ts) { case BLOCKED: sb.append("\t- blocked on " + ti.getLockInfo()); sb.append('\n'); break; case WAITING: sb.append("\t- waiting on " + ti.getLockInfo()); sb.append('\n'); break; case TIMED_WAITING: sb.append("\t- waiting on " + ti.getLockInfo()); sb.append('\n'); break; default: } } for (MonitorInfo mi : ti.getLockedMonitors()) { if (mi.getLockedStackDepth() == i) { sb.append("\t- locked " + mi); sb.append('\n'); } } } LockInfo[] locks = ti.getLockedSynchronizers(); if (locks.length > 0) { sb.append("\n\tNumber of locked synchronizers = " + locks.length); sb.append('\n'); for (LockInfo li : locks) { sb.append("\t- " + li); sb.append('\n'); } } sb.append('\n'); return sb.toString(); }