[jboss-cvs] JBossAS SVN: r74143 - trunk/system/src/main/org/jboss/system/server.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Thu Jun 5 11:00:54 EDT 2008
Author: galder.zamarreno at jboss.com
Date: 2008-06-05 11:00:54 -0400 (Thu, 05 Jun 2008)
New Revision: 74143
Modified:
trunk/system/src/main/org/jboss/system/server/ServerInfo.java
Log:
[JBAS-5163] listThreadDump now takes advantage of new JDK 6 APIs, if available, providing more detailed thread dumps. Besides, thread dumps now print deadlocks, if detected any. JDK5 reflection calls have been removed as trunk is now based in JDK5. Finally, I changed <br> so that it's properly closed, i.e. <br/>.
Modified: trunk/system/src/main/org/jboss/system/server/ServerInfo.java
===================================================================
--- trunk/system/src/main/org/jboss/system/server/ServerInfo.java 2008-06-05 14:34:47 UTC (rev 74142)
+++ trunk/system/src/main/org/jboss/system/server/ServerInfo.java 2008-06-05 15:00:54 UTC (rev 74143)
@@ -21,9 +21,16 @@
*/
package org.jboss.system.server;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryPoolMXBean;
+import java.lang.management.MemoryType;
+import java.lang.management.MemoryUsage;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
+import java.util.Arrays;
import java.util.Date;
import java.util.Enumeration;
import java.util.Iterator;
@@ -34,6 +41,7 @@
import javax.management.MBeanRegistration;
import javax.management.MBeanServer;
import javax.management.ObjectName;
+import javax.management.openmbean.CompositeData;
import org.jboss.logging.Logger;
import org.jboss.util.platform.Java;
@@ -48,6 +56,7 @@
* @author <a href="mailto:jason at planet57.com">Jason Dillon</a>
* @author <a href="mailto:marc.fleury at jboss.org">Marc Fleury</a>
* @author <a href="mailto:dimitris at jboss.org">Dimitris Andreadis</a>
+ * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
* @version $Revision$
*/
public class ServerInfo
@@ -67,46 +76,37 @@
/** used for formating timestamps (date attribute) */
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
+
+ /** Entry point for the management of the thread system */
+ private static final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
/** The cached host name for the server. */
private String hostName;
/** The cached host address for the server. */
private String hostAddress;
-
- /** The cached jdk5+ ThreadMXBean instance */
- private Object threadMXBean;
- /** The cached jdk5+ ManagementFactory.getMemoryPoolMXBeans() method */
- private Method getMemoryPoolMXBeans;
+ /** The cached jdk6+ ThreadMXBean methods */
+ private boolean isObjectMonitorUsageSupported;
+ private boolean isSynchronizerUsageSupported;
+ private Method findDeadlockedThreads;
+ private Method dumpAllThreads;
+ private Method getThreadInfoWithSyncInfo;
- /** The cached jdk5+ MemoryPoolMXBean methods */
- private Method getName;
- private Method getType;
- private Method getUsage;
- private Method getPeakUsage;
+ /** The cached jdk6+ ThreadInfo methods */
+ private Method getLockInfo;
+ private Method getLockedMonitors;
+ private Method getLockedSynchronizers;
- /** The cached jdk5+ MemoryUsage methods */
- private Method getInit;
- private Method getUsed;
- private Method getCommitted;
- private Method getMax;
+ /** The cached jdk6+ LockInfo methods */
+ private Method getClassName;
+ private Method getIdentityHashCode;
- /** The cached jdk5+ ThreadMXBean.getThreadInfo() method */
- private Method getThreadInfo;
- private Method getAllThreadIds;
- private Method getThreadCpuTime;
-
- /** The cached jdk5+ ThreadInfo methods */
- private Method getThreadName;
- private Method getThreadState;
- private Method getLockName;
- //private Method getLockOwnerId;
- //private Method getLockOwnerName;
- private Method getStackTrace;
+ /** The cached jdk6+ MonitorInfo methods */
+ private Method from;
+ private Method getLockedStackDepth;
+ private Method getLockedStackFrame;
- /** The cached jdk5+ Thread.getId() method */
- private Method getThreadId;
///////////////////////////////////////////////////////////////////////////
// JMX Hooks //
@@ -139,54 +139,36 @@
log.debug(" " + pname + ": " + System.getProperty(pname));
}
- // cache a reference to the platform ThreadMXBean
- // and related Thread/ThreadInfo methods, if available
- if (Java.isCompatible(Java.VERSION_1_5))
+ if (Java.isCompatible(Java.VERSION_1_6))
{
try
{
- ClassLoader cl = Thread.currentThread().getContextClassLoader();
- Class clazz = cl.loadClass("java.lang.management.ManagementFactory");
-
- // cache ThreadMXBean instance
- Method method = clazz.getMethod("getThreadMXBean", NO_PARAMS_SIG);
- this.threadMXBean = method.invoke(null, NO_PARAMS);
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
- // cache ManagementFactory.getMemoryPoolMXBeans() method
- this.getMemoryPoolMXBeans = clazz.getMethod("getMemoryPoolMXBeans", NO_PARAMS_SIG);
+ Class clazz = ThreadMXBean.class;
+ Method method = clazz.getMethod("isObjectMonitorUsageSupported", NO_PARAMS_SIG);
+ isObjectMonitorUsageSupported = (Boolean)method.invoke(threadMXBean, NO_PARAMS);
- // cache MemoryPoolMXBean methods
- clazz = cl.loadClass("java.lang.management.MemoryPoolMXBean");
- this.getName = clazz.getMethod("getName", NO_PARAMS_SIG);
- this.getType = clazz.getMethod("getType", NO_PARAMS_SIG);
- this.getUsage = clazz.getMethod("getUsage", NO_PARAMS_SIG);
- this.getPeakUsage = clazz.getMethod("getPeakUsage", NO_PARAMS_SIG);
+ method = clazz.getMethod("isSynchronizerUsageSupported", NO_PARAMS_SIG);
+ isSynchronizerUsageSupported = (Boolean)method.invoke(threadMXBean, NO_PARAMS);
- // cache MemoryUsage methods
- clazz = cl.loadClass("java.lang.management.MemoryUsage");
- this.getInit = clazz.getMethod("getInit", NO_PARAMS_SIG);
- this.getUsed = clazz.getMethod("getUsed", NO_PARAMS_SIG);
- this.getCommitted = clazz.getMethod("getCommitted", NO_PARAMS_SIG);
- this.getMax = clazz.getMethod("getMax", NO_PARAMS_SIG);
+ this.findDeadlockedThreads = clazz.getMethod("findDeadlockedThreads", NO_PARAMS_SIG);
+ this.dumpAllThreads = clazz.getMethod("dumpAllThreads", new Class[] { Boolean.TYPE, Boolean.TYPE } );
+ this.getThreadInfoWithSyncInfo = clazz.getMethod("getThreadInfo", new Class[] { long[].class , Boolean.TYPE, Boolean.TYPE});
- // cache ThreadMXBean.getThreadInfo() method
- clazz = cl.loadClass("java.lang.management.ThreadMXBean");
- this.getThreadInfo = clazz.getMethod("getThreadInfo", new Class[] { Long.TYPE, Integer.TYPE } );
- this.getAllThreadIds = clazz.getMethod("getAllThreadIds", NO_PARAMS_SIG );
- this.getThreadCpuTime = clazz.getMethod("getThreadCpuTime", new Class[] { Long.TYPE } );
-
- // cache ThreadInfo methods
- clazz = cl.loadClass("java.lang.management.ThreadInfo");
- this.getThreadName = clazz.getMethod("getThreadName", NO_PARAMS_SIG);
- this.getThreadState = clazz.getMethod("getThreadState", NO_PARAMS_SIG);
- this.getLockName = clazz.getMethod("getLockName", NO_PARAMS_SIG);
- //this.getLockOwnerId = clazz.getMethod("getLockOwnerId", NO_PARAMS_SIG);
- //this.getLockOwnerName = clazz.getMethod("getLockOwnerName", NO_PARAMS_SIG);
- this.getStackTrace = clazz.getMethod("getStackTrace", NO_PARAMS_SIG);
+ clazz = ThreadInfo.class;
+ this.getLockInfo = clazz.getMethod("getLockInfo", NO_PARAMS_SIG);
+ this.getLockedMonitors = clazz.getMethod("getLockedMonitors", NO_PARAMS_SIG);
+ this.getLockedSynchronizers = clazz.getMethod("getLockedSynchronizers", NO_PARAMS_SIG);
- // cache Thread.getId() method
- clazz = Thread.class;
- this.getThreadId = clazz.getMethod("getId", NO_PARAMS_SIG);
+ clazz = cl.loadClass("java.lang.management.LockInfo");
+ this.getClassName = clazz.getMethod("getClassName", NO_PARAMS_SIG);
+ this.getIdentityHashCode = clazz.getMethod("getIdentityHashCode", NO_PARAMS_SIG);
+
+ clazz = cl.loadClass("java.lang.management.MonitorInfo");
+ this.from = clazz.getMethod("from", new Class[] { CompositeData.class });
+ this.getLockedStackDepth = clazz.getMethod("getLockedStackDepth", NO_PARAMS_SIG);
+ this.getLockedStackFrame = clazz.getMethod("getLockedStackFrame", NO_PARAMS_SIG);
}
catch (Exception e)
{
@@ -364,81 +346,66 @@
*/
public String listMemoryPools(boolean fancy)
{
- if (getMemoryPoolMXBeans != null)
+ StringBuffer sbuf = new StringBuffer(4196);
+
+ // get the pools
+ List<MemoryPoolMXBean> poolList = ManagementFactory.getMemoryPoolMXBeans();
+ sbuf.append("<b>Total Memory Pools:</b> ").append(poolList.size());
+ sbuf.append("<blockquote>");
+ for (MemoryPoolMXBean pool : poolList)
{
- // running under jdk5+
- StringBuffer sbuf = new StringBuffer(4196);
- try
+ // MemoryPoolMXBean instance
+ String name = pool.getName();
+ // enum MemoryType
+ MemoryType type = pool.getType();
+ sbuf.append("<b>Pool: ").append(name);
+ sbuf.append("</b> (").append(type).append(")");
+
+ // PeakUsage/CurrentUsage
+ MemoryUsage peakUsage = pool.getPeakUsage();
+ MemoryUsage usage = pool.getUsage();
+
+ sbuf.append("<blockquote>");
+ if (usage != null && peakUsage != null)
{
- // get the pools
- List poolList = (List)getMemoryPoolMXBeans.invoke(null, NO_PARAMS);
- sbuf.append("<b>Total Memory Pools:</b> ").append(poolList.size());
- sbuf.append("<blockquote>");
- for (Iterator i = poolList.iterator(); i.hasNext(); )
- {
- // MemoryPoolMXBean instance
- Object pool = i.next();
- String name = (String)getName.invoke(pool, NO_PARAMS);
- // enum MemoryType
- Object type = getType.invoke(pool, NO_PARAMS);
- sbuf.append("<b>Pool: ").append(name);
- sbuf.append("</b> (").append(type).append(")");
-
- // PeakUsage/CurrentUsage
- Object peakUsage = getPeakUsage.invoke(pool, NO_PARAMS);
- Object usage = getUsage.invoke(pool, NO_PARAMS);
-
- sbuf.append("<blockquote>");
- if (usage != null && peakUsage != null)
- {
- Long init = (Long)getInit.invoke(peakUsage, NO_PARAMS);
- Long used = (Long)getUsed.invoke(peakUsage, NO_PARAMS);
- Long committed = (Long)getCommitted.invoke(peakUsage, NO_PARAMS);
- Long max = (Long)getMax.invoke(peakUsage, NO_PARAMS);
+ Long init = peakUsage.getInit();
+ Long used = peakUsage.getUsed();
+ Long committed = peakUsage.getCommitted();
+ Long max = peakUsage.getMax();
+
+ sbuf.append("Peak Usage : ");
+ sbuf.append("init:").append(init);
+ sbuf.append(", used:").append(used);
+ sbuf.append(", committed:").append(committed);
+ sbuf.append(", max:").append(max);
+ sbuf.append("<br/>");
- sbuf.append("Peak Usage : ");
- sbuf.append("init:").append(init);
- sbuf.append(", used:").append(used);
- sbuf.append(", committed:").append(committed);
- sbuf.append(", max:").append(max);
- sbuf.append("<br>");
-
- init = (Long)getInit.invoke(usage, NO_PARAMS);
- used = (Long)getUsed.invoke(usage, NO_PARAMS);
- committed = (Long)getCommitted.invoke(usage, NO_PARAMS);
- max = (Long)getMax.invoke(usage, NO_PARAMS);
+ init = usage.getInit();
+ used = usage.getUsed();
+ committed = usage.getCommitted();
+ max = usage.getMax();
- sbuf.append("Current Usage : ");
- sbuf.append("init:").append(init);
- sbuf.append(", used:").append(used);
- sbuf.append(", committed:").append(committed);
- sbuf.append(", max:").append(max);
-
- if (fancy)
- {
- TextGraphHelper.poolUsage(sbuf, used.longValue(), committed.longValue(), max.longValue());
- }
- }
- else
- {
- sbuf.append("Memory pool NOT valid!");
- }
- sbuf.append("</blockquote><br>");
+ sbuf.append("Current Usage : ");
+ sbuf.append("init:").append(init);
+ sbuf.append(", used:").append(used);
+ sbuf.append(", committed:").append(committed);
+ sbuf.append(", max:").append(max);
+
+ if (fancy)
+ {
+ TextGraphHelper.poolUsage(sbuf, used.longValue(), committed.longValue(), max.longValue());
}
- sbuf.append("</blockquote>");
}
- catch (Exception e)
+ else
{
- // ignore
+ sbuf.append("Memory pool NOT valid!");
}
- return sbuf.toString();
+ sbuf.append("</blockquote><br/>");
}
- else
- {
- return "<b>Memory pool information available only under a JDK5+ compatible JVM!</b>";
- }
+
+ return sbuf.toString();
}
-
+
public Integer getActiveThreadCount()
{
return new Integer(getRootThreadGroup().activeCount());
@@ -461,15 +428,20 @@
// activeCount() and activeGroupCount()
ThreadGroupCount count = new ThreadGroupCount();
- // traverse
- String threadGroupInfo = getThreadGroupInfo(root, count);
+ StringBuffer rc = new StringBuffer();
- // attach counters
+ // Find deadlocks, if there're any first, so that they're visible first thing
+ findDeadlockedThreads(rc);
+
+ // Traverse thread dump
+ getThreadGroupInfo(root, count, rc);
+
+ // Attach counters
String threadDump =
- "<b>Total Threads:</b> " + count.threads + "<br>" +
- "<b>Total Thread Groups:</b> " + count.groups + "<br>" +
- "<b>Timestamp:</b> " + dateFormat.format(new Date()) + "<br>" +
- threadGroupInfo;
+ "<b>Total Threads:</b> " + count.threads + "<br/>" +
+ "<b>Total Thread Groups:</b> " + count.groups + "<br/>" +
+ "<b>Timestamp:</b> " + dateFormat.format(new Date()) + "<br/>" +
+ rc.toString();
return threadDump;
}
@@ -514,33 +486,23 @@
*/
private Set<ThreadCPU> getThreadCpuUtilization()
{
- if (threadMXBean == null)
- return null;
+ TreeSet<ThreadCPU> result = new TreeSet<ThreadCPU>();
- try
+ long[] threads = threadMXBean.getAllThreadIds();
+ for (int i = 0; i < threads.length; ++i)
{
- TreeSet<ThreadCPU> result = new TreeSet<ThreadCPU>();
- long[] threads = (long[]) getAllThreadIds.invoke(threadMXBean, NO_PARAMS);
- for (int i = 0; i < threads.length; ++i)
+ Long id = new Long(threads[i]);
+ Long cpuTime = threadMXBean.getThreadCpuTime(id);
+ ThreadInfo threadInfo = threadMXBean.getThreadInfo(id, ZERO );
+ if (threadInfo != null)
{
- Long id = new Long(threads[i]);
- Long cpuTime = (Long) getThreadCpuTime.invoke(threadMXBean, new Object[] { id });
- Object threadInfo = getThreadInfo.invoke(threadMXBean, new Object[] { id, ZERO });
- if (threadInfo != null)
- {
- String name = (String) getThreadName.invoke(threadInfo, NO_PARAMS);
- result.add(new ThreadCPU(name, cpuTime.longValue()));
- }
+ String name = threadInfo.getThreadName();
+ result.add(new ThreadCPU(name, cpuTime.longValue()));
}
- return result;
}
- catch (Exception e)
- {
- log.warn("Error retrieving thread cpu utiliation", e);
- return null;
- }
+ return result;
}
-
+
/*
* Traverse to the root thread group
*/
@@ -558,14 +520,32 @@
/*
* Recurse inside ThreadGroups to create the thread dump
*/
- private String getThreadGroupInfo(ThreadGroup group, ThreadGroupCount count)
+ private void getThreadGroupInfo(ThreadGroup group, ThreadGroupCount count, StringBuffer rc)
{
- StringBuffer rc = new StringBuffer();
-
+ if (Java.isCompatible(Java.VERSION_1_6) &&
+ (isObjectMonitorUsageSupported || isSynchronizerUsageSupported))
+ {
+ /* We're running JDK6+ and either object monitor or ownable
+ * synchronizers are supported by the JVM */
+ log.debug("Generate a thread dump [show monitors = " + isObjectMonitorUsageSupported + ", show ownable synchronizers = " + isSynchronizerUsageSupported + "]");
+ getThreadGroupInfoWithLocks(group, count, rc);
+ }
+ else
+ {
+ /* If we're running JDK5, or JDK6 but neither monitor nor
+ * synchronisers cannot be retrieved, we use standard thread dump
+ * format. */
+ log.debug("Generate a thread dump without locks.");
+ getThreadGroupInfoWithoutLocks(group, count, rc);
+ }
+ }
+
+ private void getThreadGroupInfoWithoutLocks(ThreadGroup group, ThreadGroupCount count, StringBuffer rc)
+ {
// Visit one more group
count.groups++;
- rc.append("<br><b>");
+ rc.append("<br/><b>");
rc.append("Thread Group: " + group.getName());
rc.append("</b> : ");
rc.append("max priority:" + group.getMaxPriority() +
@@ -583,8 +563,8 @@
rc.append("Thread: " + threads[i].getName());
rc.append("</b> : ");
rc.append("priority:" + threads[i].getPriority() +
- ", demon:" + threads[i].isDaemon());
- // Output extra info with jdk5+, or just <br>
+ ", demon:" + threads[i].isDaemon() + ", ");
+ // Output extra info with jdk5+, or just <br/>
outputJdk5ThreadMXBeanInfo(rc, threads[i]);
}
@@ -592,71 +572,267 @@
group.enumerate(groups, false);
for (int i= 0; i < groups.length && groups[i] != null; i++)
{
- rc.append(getThreadGroupInfo(groups[i], count));
+ getThreadGroupInfoWithoutLocks(groups[i], count, rc);
}
+ rc.append("</blockquote>");
+ }
+
+ private void getThreadGroupInfoWithLocks(ThreadGroup group, ThreadGroupCount count, StringBuffer rc)
+ {
+ // Visit one more group
+ count.groups++;
+
+ rc.append("<br/><b>");
+ rc.append("Thread Group: " + group.getName());
+ rc.append("</b> : ");
+ rc.append("max priority:" + group.getMaxPriority() +
+ ", demon:" + group.isDaemon());
+
+ rc.append("<blockquote>");
+ Thread threads[]= new Thread[group.activeCount()];
+ group.enumerate(threads, false);
+
+ long[] idsTmp = new long[threads.length];
+ int numberNonNullThreads = 0;
+ for (int i= 0; i < threads.length && threads[i] != null; i++)
+ {
+ if (log.isTraceEnabled())
+ {
+ log.trace("Adding " + threads[i] + " with id=" + threads[i].getId());
+ }
+ idsTmp[i] = threads[i].getId();
+ numberNonNullThreads++;
+ }
+
+ long[] ids = new long[numberNonNullThreads];
+ System.arraycopy(idsTmp, 0, ids, 0, numberNonNullThreads);
+
+ if (log.isTraceEnabled())
+ {
+ log.trace("List of ids after trimming " + Arrays.toString(ids));
+ }
+
+ try
+ {
+ ThreadInfo[] infos = (ThreadInfo[])getThreadInfoWithSyncInfo.invoke(threadMXBean,
+ new Object[] {ids, isObjectMonitorUsageSupported, isSynchronizerUsageSupported});
+
+ for (int i= 0; i < infos.length && threads[i] != null; i++)
+ {
+ // Visit one more thread
+ count.threads++;
+
+ rc.append("<b>");
+ rc.append("Thread: " + infos[i].getThreadName());
+ rc.append("</b> : ");
+ rc.append("priority:" + threads[i].getPriority() +
+ ", demon:" + threads[i].isDaemon() + ", ");
+ // Output extra info with jdk6+
+ outputJdk6ThreadMXBeanInfo(rc, infos[i]);
+ }
+
+ ThreadGroup groups[]= new ThreadGroup[group.activeGroupCount()];
+ group.enumerate(groups, false);
+ for (int i= 0; i < groups.length && groups[i] != null; i++)
+ {
+ getThreadGroupInfoWithLocks(groups[i], count, rc);
+ }
+ }
+ catch(Exception ignore)
+ {
+ log.debug("Exception to be ignored", ignore);
+ }
+
rc.append("</blockquote>");
-
- return rc.toString();
}
+
/*
* Complete the output of thread info, with optional stuff
* when running under jdk5+, or just change line.
*/
private void outputJdk5ThreadMXBeanInfo(StringBuffer sbuf, Thread thread)
{
- // if ThreadMXBean has been found, we run under jdk5+
- if (threadMXBean != null)
+ // Get the threadId
+ Long threadId = thread.getId();
+
+ // Get the ThreadInfo object for that threadId, max StackTraceElement depth
+ ThreadInfo threadInfo = threadMXBean.getThreadInfo(threadId, new Integer(Integer.MAX_VALUE));
+
+ outputJdk5ThreadMXBeanInfo(sbuf, threadInfo);
+ }
+
+ /*
+ * Complete the output of thread info, with optional stuff when running
+ * under jdk5+ or jdk6 without object monitor usage and object synchronizer
+ * usage capabilities, or just change line.
+ */
+ private void outputJdk5ThreadMXBeanInfo(StringBuffer sbuf, ThreadInfo threadInfo)
+ {
+ // JBAS-3838, thread might not be alive
+ if (threadInfo != null)
{
- // use reflection all the way, until we base on jdk5
- try
+ // get misc info from ThreadInfo
+ Thread.State threadState = threadInfo.getThreadState(); // enum
+ String lockName = threadInfo.getLockName();
+ StackTraceElement[] stackTrace = threadInfo.getStackTrace();
+
+ Long threadId = threadInfo.getThreadId();
+ sbuf.append("threadId:").append(threadId);
+ sbuf.append(", threadState:").append(threadState);
+ sbuf.append("<br/>");
+ if (stackTrace.length > 0)
{
- // get the threadId
- Long threadId = (Long)getThreadId.invoke(thread, NO_PARAMS);
- sbuf.append(", threadId:").append(threadId);
+ sbuf.append("<blockquote>");
+
+ printLockName(sbuf, "waiting on", lockName);
+
+ for (int i = 0; i < stackTrace.length; i++)
+ {
+ sbuf.append(stackTrace[i]).append("<br/>");
+ }
+ sbuf.append("</blockquote>");
+ }
+ }
+ else
+ {
+ sbuf.append("<br/>");
+ }
+ }
+
+ /*
+ * Complete the output of thread info, with optional stuff
+ * when running under jdk6+, or just change line.
+ */
+ private void outputJdk6ThreadMXBeanInfo(StringBuffer sbuf, ThreadInfo threadInfo) throws Exception
+ {
+ // get the threadId
+ Long threadId = threadInfo.getThreadId();
+ sbuf.append("threadId:").append(threadId);
- // get the ThreadInfo object for that threadId, max StackTraceElement depth
- Object threadInfo = getThreadInfo.invoke(threadMXBean,
- new Object[] { threadId, new Integer(Integer.MAX_VALUE) });
- // JBAS-3838, thread might not be alive
- if (threadInfo != null)
+ if (threadInfo != null)
+ {
+ // get misc info from ThreadInfo
+ Thread.State threadState = threadInfo.getThreadState(); // enum
+ String lockName = threadInfo.getLockName();
+ StackTraceElement[] stackTrace = threadInfo.getStackTrace();
+ Object[] monitors = (Object[])getLockedMonitors.invoke(threadInfo, NO_PARAMS);
+
+ sbuf.append(", threadState:").append(threadState);
+ sbuf.append("<br/>");
+ if (stackTrace.length > 0)
+ {
+ sbuf.append("<blockquote>");
+
+ printLockName(sbuf, "waiting on", lockName);
+
+ for (int i = 0; i < stackTrace.length; i++)
{
- // get misc info from ThreadInfo
- Object threadState = getThreadState.invoke(threadInfo, NO_PARAMS); // enum
- String lockName = (String)getLockName.invoke(threadInfo, NO_PARAMS);
- //Long lockOwnerId = (Long)getLockOwnerId.invoke(threadInfo, NO_PARAMS);
- //String lockOwnerName = (String)getLockOwnerName.invoke(threadInfo, NO_PARAMS);
- Object[] stackTrace = (Object[])getStackTrace.invoke(threadInfo, NO_PARAMS);
-
- sbuf.append(", threadState:").append(threadState);
- sbuf.append(", lockName:").append(lockName);
- //sbuf.append(", lockOwnerId:").append(lockOwnerId);
- //sbuf.append(", lockOwnerName:").append(lockOwnerName);
- sbuf.append("<br>");
- if (stackTrace.length > 0)
+ sbuf.append(stackTrace[i]).append("<br/>");
+ for (Object monitor : monitors)
{
- sbuf.append("<blockquote>");
- for (int i = 0; i < stackTrace.length; i++)
+ int lockedStackDepth = (Integer)getLockedStackDepth.invoke(monitor, NO_PARAMS);
+ if (lockedStackDepth == i)
{
- sbuf.append(stackTrace[i]).append("<br>");
+ printLockName(sbuf, "locked", monitor.toString());
}
- sbuf.append("</blockquote>");
}
}
- else
+
+ Object[] synchronizers = (Object[])getLockedSynchronizers.invoke(threadInfo, NO_PARAMS);
+ if (synchronizers.length > 0)
{
- sbuf.append("<br>");
+ sbuf.append("<br/>").append("<b>Locked synchronizers</b> : ").append("<br/>");
+ for (Object synchronizer : synchronizers)
+ {
+ printLockName(sbuf, "locked", synchronizer.toString());
+ }
}
+
+ sbuf.append("</blockquote>");
+ }
+ }
+ else
+ {
+ sbuf.append("<br/>");
+ }
+ }
+
+ private void printLockName(StringBuffer sbuf, String status, String lockName)
+ {
+ if (lockName != null)
+ {
+ String[] lockInfo = lockName.split("@");
+ sbuf.append("- " + status + " <0x" + lockInfo[1] + "> (a " + lockInfo[0] + ")").append("<br/>");
+ }
+ }
+
+ private void findDeadlockedThreads(StringBuffer rc)
+ {
+ if (Java.isCompatible(Java.VERSION_1_6) && isSynchronizerUsageSupported)
+ {
+ findDeadlockedThreadsMonitorsOrSynchronisers(rc);
+ }
+ else
+ {
+ findDeadlockedThreadsOnlyMonitors(rc);
+ }
+ }
+
+ private void findDeadlockedThreadsMonitorsOrSynchronisers(StringBuffer sb)
+ {
+ try
+ {
+ long[] ids = (long[])findDeadlockedThreads.invoke(threadMXBean, NO_PARAMS);
+ if (ids == null)
+ {
+ return;
}
- catch (Exception ignore)
+
+ ThreadInfo[] threadsInfo = (ThreadInfo[])getThreadInfoWithSyncInfo.invoke(threadMXBean,
+ new Object[] {ids, isObjectMonitorUsageSupported, isSynchronizerUsageSupported});
+
+ sb.append("<br/><b>Found deadlock(s)</b> : <br/><br/>");
+
+ for (ThreadInfo threadInfo : threadsInfo)
{
- // empty
+ sb.append("<b>");
+ sb.append("Thread: " + threadInfo.getThreadName());
+ sb.append("</b> : ");
+ outputJdk6ThreadMXBeanInfo(sb, threadInfo);
+ }
+ }
+ catch(Exception ignore)
+ {
+ log.debug("Exception to be ignored", ignore);
+ }
+ }
+
+ private void findDeadlockedThreadsOnlyMonitors(StringBuffer sb)
+ {
+ try
+ {
+ long[] ids = threadMXBean.findMonitorDeadlockedThreads();
+ if (ids == null)
+ {
+ return;
}
+
+ ThreadInfo[] threadsInfo = threadMXBean.getThreadInfo(ids, Integer.MAX_VALUE);
+
+ sb.append("<br/><b>Found deadlock(s)</b> : <br/><br/>");
+
+ for (ThreadInfo threadInfo : threadsInfo)
+ {
+ sb.append("<b>");
+ sb.append("Thread: " + threadInfo.getThreadName());
+ sb.append("</b> : ");
+ outputJdk5ThreadMXBeanInfo(sb, threadInfo);
+ }
}
- else
+ catch(Exception ignore)
{
- // no jdk5+ info to add, just change line
- sbuf.append("<br>");
+ log.debug("Exception to be ignored", ignore);
}
}
@@ -765,9 +941,9 @@
int localCommitted = (int)(factor * committed / assumedMax);
int localMax = factor;
- sbuf.append("<blockquote><br>");
- sbuf.append(baseline, 0, localCommitted).append("| committed:").append(outputNumber(committed)).append("<br>");
- sbuf.append(fixedline).append("<br>");
+ sbuf.append("<blockquote><br/>");
+ sbuf.append(baseline, 0, localCommitted).append("| committed:").append(outputNumber(committed)).append("<br/>");
+ sbuf.append(fixedline).append("<br/>");
// the difficult part
sbuf.append(barline, 0, localUsed);
@@ -782,9 +958,9 @@
sbuf.append(spaces, 0, localMax - localCommitted - 1);
sbuf.append('|');
}
- sbuf.append(" max:").append(outputNumber(max)).append("<br>");
+ sbuf.append(" max:").append(outputNumber(max)).append("<br/>");
- sbuf.append(fixedline).append("<br>");
+ sbuf.append(fixedline).append("<br/>");
sbuf.append(baseline, 0, localUsed).append("| used:").append(outputNumber(used));
sbuf.append("</blockquote>");
}
More information about the jboss-cvs-commits
mailing list