/* * Analyzer.java * * This file is part of TDA - Thread Dump Analysis Tool. * * Foobar is free software; you can redistribute it and/or modify * it under the terms of the Lesser GNU General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Lesser GNU General Public License for more details. * * You should have received a copy of the Lesser GNU General Public License * along with Foobar; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * $Id: Analyzer.java,v 1.3 2008-01-28 09:29:34 irockel Exp $ */ package com.pironet.tda; import java.io.Serializable; /** * analyze the given thread dump. * * @author irockel */ public class Analyzer implements Serializable { ThreadDumpInfo tdi; /** * generate a dump analyzer for the given thread dump. * @param tdi the thread dump to analyze. */ public Analyzer(ThreadDumpInfo tdi) { this.tdi = tdi; } /** * analyze the given data and generate htmlified hints * @return html-text containing hints, empty strings if no hints can * be given. */ public String analyzeDump() { // check for possible hot spots concerning this thread dump StringBuffer statData = new StringBuffer(); int deadlocks = tdi.getDeadlocks() == null ? 0 : tdi.getDeadlocks().getNodeCount(); int threadCount = tdi.getThreads() == null ? 0 : tdi.getThreads().getNodeCount(); int waiting = tdi.getWaitingThreads() == null ? 0 : tdi.getWaitingThreads().getNodeCount(); int sleeping = tdi.getSleepingThreads() == null ? 0 : tdi.getSleepingThreads().getNodeCount(); int overallThreadsWaitingWithoutLocks = tdi.getOverallThreadsWaitingWithoutLocksCount(); int monitorsWithoutLocksCount = tdi.getMonitorsWithoutLocks() == null ? 0 : tdi.getMonitorsWithoutLocks().getNodeCount(); // check if a lot of threads are in state "waiting" if ((deadlocks == 0) && (threadCount > 0) && ((waiting / (threadCount / 100.0)) > 10.0)) { statData.append("<tr bgcolor=\"#ffffff\"<td></td></tr>"); statData.append("<tr bgcolor=\"#cccccc\"><td colspan=2><font face=System " + "><p>" + (int) (waiting / (threadCount / 100.0)) + "% of all threads are waiting for a monitor to become available again.</p><br>"); statData.append("This might indicate a congestion or even a deadlock. If a monitor doesn't have a locking thread, it might be<br>"); statData.append("hold by some external resource or system thread. You should check the <a href=\"wait://\">waiting threads</a>.<br></td></tr>"); } else if (deadlocks > 0) { statData.append("<tr bgcolor=\"#ffffff\"<td></td></tr>"); statData.append("<tr bgcolor=\"#cccccc\"><td colspan=2><font face=System " + "><p>The JVM has detected " + deadlocks + " deadlock(s) in the thread dump. You should check the <br><a href=\"dead://\">deadlocks</a> for further information.</p><br>"); } // check if a lot of threads are in state "waiting" if ((threadCount > 0) && ((sleeping / (threadCount / 100.0)) > 25.0)) { statData.append("<tr bgcolor=\"#ffffff\"<td></td></tr>"); statData.append("<tr bgcolor=\"#cccccc\"><td colspan=2><font face=System" + "><p>" + (int) (sleeping / (threadCount / 100.0)) + "% of all threads are sleeping on a monitor.</p><br>"); statData.append("This might indicate they are waiting for some external resource (e.g. database) which is overloaded<br>"); statData.append("or not available or are just waiting to get to do something (idle threads).<br>"); statData.append("You should check the <a href=\"sleep://\">sleeping threads</a> with a filter excluding all idle threads.</td></tr>"); } // display an info if there are monitors without locking threads if (monitorsWithoutLocksCount > 0) { statData.append("<tr bgcolor=\"#ffffff\"<td></td></tr>"); statData.append("<tr bgcolor=\"#cccccc\"><td colspan=2><font face=System" + "><p>This thread dump contains monitors without a locking thread information.<br>"); statData.append("This means, the monitor is hold by a system thread or some external resource.</p<br>"); statData.append("You should check the monitors without locking threads for more information.<br></td></tr>"); } // check for indications for running garbage collector if ((threadCount > 0) && (overallThreadsWaitingWithoutLocks / (threadCount / 100.0) > 50.0)) { statData.append("<tr bgcolor=\"#ffffff\"<td></td></tr>"); statData.append("<tr bgcolor=\"#cccccc\"><td colspan=2><font face=System " + "<p>" + (int) (overallThreadsWaitingWithoutLocks / (threadCount / 100.0)) + "% of all threads are waiting for a monitor without an application "); statData.append("thread holding it.<br> This indicates a congestion. It is very likely the garbage collector is running "); statData.append("and is blocking the monitors.</p<br>"); statData.append("You should check the monitors without locking threads for more information on the blocked threads.<br>"); statData.append("You also should analyze the garbage collector behaviour. Go to the "); statData.append("<a href=\"http://www.tagtraum.com/gcviewer.html\">GCViewer-Homepage</a> for more<br>"); statData.append(" information on how to do this.</td></tr>"); } return statData.toString(); } }