package au.com.vaadinutils.util; import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; /** * This class implements a daemon thread which periodically checks to see if * there are any threads deadlocked, and reports the situation if there are. * Note: this class calls System.exit(1) if it finds a deadlock. * * @author Eric Kolotyluk */ public enum DeadlockFinder implements Runnable { SINGLETON; private static final int TEST_INTERVAL = 20000; private static final Logger LOG = LogManager.getLogger(DeadlockFinder.class); private long count; ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); private Thread finder = null; public void start() { if (finder == null) { finder = new Thread(this); finder.setDaemon(true); finder.setName("DeadlockFinder"); //$NON-NLS-1$ finder.setPriority(Thread.MIN_PRIORITY + 1); finder.start(); } } public void run() { LOG.info("running, priority = " + finder.getPriority()); //$NON-NLS-1$ try { for (;;) { Thread.sleep(TEST_INTERVAL); // Note: the following can be an expensive operation long[] threads = threadMXBean.findMonitorDeadlockedThreads(); if (threads == null || threads.length == 0) { // Try not to flood the log with these messages.EK if (count++ < 100 || count % 100 == 0) LOG.debug("no threads are deadlocked"); //$NON-NLS-1$ continue; } LOG.fatal(threads.length + " threads deadlocked"); //$NON-NLS-1$ ThreadInfo[] threadInfoArray = threadMXBean.getThreadInfo(threads, Integer.MAX_VALUE); for (ThreadInfo threadInfo : threadInfoArray) { LOG.error("\n----------------------------"); //$NON-NLS-1$ LOG.error("ThreadName = " + threadInfo.getThreadName()); //$NON-NLS-1$ LOG.error("LockName = " + threadInfo.getLockName()); //$NON-NLS-1$ LOG.error("LockOwnerName = " + threadInfo.getLockOwnerName()); //$NON-NLS-1$ StackTraceElement[] stackTrace = threadInfo.getStackTrace(); if (stackTrace == null || stackTrace.length == 0) LOG.error("no stack trace"); //$NON-NLS-1$ else { LOG.error("stack trace..."); //$NON-NLS-1$ for (StackTraceElement stackTraceElement : stackTrace) { LOG.error(stackTraceElement.toString()); } } } // If we get here we have deadlocked threads so shutdown having // already logged the problem. System.exit(1); } } catch (InterruptedException e) { // just return } } }