diff options
Diffstat (limited to 'simple/simple-http/src/test/java/org/simpleframework/http/core/ThreadDumper.java')
-rw-r--r-- | simple/simple-http/src/test/java/org/simpleframework/http/core/ThreadDumper.java | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/simple/simple-http/src/test/java/org/simpleframework/http/core/ThreadDumper.java b/simple/simple-http/src/test/java/org/simpleframework/http/core/ThreadDumper.java new file mode 100644 index 0000000..85960ed --- /dev/null +++ b/simple/simple-http/src/test/java/org/simpleframework/http/core/ThreadDumper.java @@ -0,0 +1,183 @@ +package org.simpleframework.http.core; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.management.ManagementFactory; +import java.lang.management.ThreadInfo; +import java.lang.management.ThreadMXBean; +import java.util.Collections; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CountDownLatch; + + +public class ThreadDumper extends Thread { + + private static String INDENT = " "; + private CountDownLatch latch; + private volatile boolean dead; + private int wait; + + public ThreadDumper() { + this(10000); + } + + public ThreadDumper(int wait) { + this.latch = new CountDownLatch(1); + this.wait = wait; + } + + public void waitUntilStarted() throws InterruptedException{ + latch.await(); + } + + public void kill(){ + try { + Thread.sleep(1000); + dead = true; + dumpThreadInfo(); + }catch(Exception e){ + e.printStackTrace(); + } + } + public void run() { + while(!dead) { + try{ + latch.countDown(); + dumpThreadInfo(); + findDeadlock(); + Thread.sleep(wait); + }catch(Exception e){ + e.printStackTrace(); + } + } + } + public String dumpThreads() { + Map<Thread, StackTraceElement[]> stackTraces = Thread.getAllStackTraces(); + return generateDump(stackTraces); + } + + public static String dumpCurrentThread() { + Thread currentThread = Thread.currentThread(); + StackTraceElement[] stackTrace = currentThread.getStackTrace(); + Map<Thread, StackTraceElement[]> stackTraces = Collections.singletonMap(currentThread, stackTrace); + return generateDump(stackTraces); + + } + + private static String generateDump(Map<Thread, StackTraceElement[]> stackTraces) { + StringBuilder builder = new StringBuilder(); + + builder.append("<pre>"); + builder.append("<b>Full Java thread dump</b>"); + builder.append("\n"); + + Set<Thread> threads = stackTraces.keySet(); + + for (Thread thread : threads) { + StackTraceElement[] stackElements = stackTraces.get(thread); + + generateDescription(thread, builder); + generateStackFrames(stackElements, builder); + } + builder.append("</pre>"); + return builder.toString(); + } + + private static void generateStackFrames(StackTraceElement[] stackElements, StringBuilder builder) { + for (StackTraceElement stackTraceElement : stackElements) { + builder.append(" at "); + builder.append(stackTraceElement); + builder.append("\n"); + } + } + + private static void generateDescription(Thread thread, StringBuilder builder) { + Thread.State threadState = thread.getState(); + String threadName = thread.getName(); + long threadId = thread.getId(); + + builder.append("\n"); + builder.append("<b>"); + builder.append(threadName); + builder.append("</b> Id="); + builder.append(threadId); + builder.append(" in "); + builder.append(threadState); + builder.append("\n"); + } + + /** + * Prints the thread dump information to System.out. + */ + public static void dumpThreadInfo(){ + System.out.println(getThreadInfo()); + } + + public static String getThreadInfo() { + ThreadMXBean tmbean = ManagementFactory.getThreadMXBean(); + long[] tids = tmbean.getAllThreadIds(); + ThreadInfo[] tinfos = tmbean.getThreadInfo(tids, Integer.MAX_VALUE); + StringWriter str = new StringWriter(); + PrintWriter log = new PrintWriter(str); + log.println("Full Java thread dump"); + + for (ThreadInfo ti : tinfos) { + printThreadInfo(ti, log); + } + log.flush(); + return str.toString(); + } + + private static void printThreadInfo(ThreadInfo ti, PrintWriter log) { + if(ti != null) { + StringBuilder sb = new StringBuilder("\"" + ti.getThreadName() + "\"" + + " Id=" + ti.getThreadId() + + " in " + ti.getThreadState()); + if (ti.getLockName() != null) { + sb.append(" on lock=" + ti.getLockName()); + } + if (ti.isSuspended()) { + sb.append(" (suspended)"); + } + if (ti.isInNative()) { + sb.append(" (running in native)"); + } + log.println(sb.toString()); + if (ti.getLockOwnerName() != null) { + log.println(INDENT + " owned by " + ti.getLockOwnerName() + + " Id=" + ti.getLockOwnerId()); + } + for (StackTraceElement ste : ti.getStackTrace()) { + log.println(INDENT + "at " + ste.toString()); + } + log.println(); + } + } + + /** + * Checks if any threads are deadlocked. If any, print + * the thread dump information. + */ + public static boolean findDeadlock() { + ThreadMXBean tmbean = ManagementFactory.getThreadMXBean(); + long[] tids = tmbean.findMonitorDeadlockedThreads(); + if (tids == null) { + return false; + } else { + StringWriter str = new StringWriter(); + PrintWriter log = new PrintWriter(str); + + tids = tmbean.getAllThreadIds(); + System.out.println("Deadlock found :-"); + ThreadInfo[] tinfos = tmbean.getThreadInfo(tids, Integer.MAX_VALUE); + for (ThreadInfo ti : tinfos) { + printThreadInfo(ti, log); + } + log.flush(); + System.out.println(str.toString()); + return true; + } + } + +} |