package org.jactr.tools.deadlock;
/*
* default logging
*/
import java.io.FileWriter;
import java.io.PrintWriter;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.lang.reflect.Method;
import java.util.Arrays;
import javax.management.MBeanServer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.commonreality.time.impl.ClockInterrogator;
import org.commonreality.util.LockUtilities;
public class DeadLockUtilities
{
/**
* Logger definition
*/
static private final transient Log LOGGER = LogFactory
.getLog(DeadLockUtilities.class);
/**
* Attempt to dump the heap to file
*
* @param fileName
* @param live
*/
static public void dumpHeap(String fileName, boolean live)
{
// initialize hotspot diagnostic MBean
try
{
Class clazz = Class.forName("com.sun.management.HotSpotDiagnosticMXBean");
Method m = clazz.getMethod("dumpHeap", String.class, boolean.class);
m.invoke(getHotspotMBean(), fileName, live);
}
catch (RuntimeException re)
{
LOGGER.error("", re);
}
catch (Exception exp)
{
LOGGER.error("", exp);
}
}
// get the hotspot diagnostic MBean from the
// platform MBean server
static private Object getHotspotMBean()
{
try
{
String HOTSPOT_BEAN_NAME = "com.sun.management:type=HotSpotDiagnostic";
Class clazz = Class.forName("com.sun.management.HotSpotDiagnosticMXBean");
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
Object bean = ManagementFactory.newPlatformMXBeanProxy(server,
HOTSPOT_BEAN_NAME, clazz);
return bean;
}
catch (RuntimeException re)
{
throw re;
}
catch (Exception exp)
{
throw new RuntimeException(exp);
}
}
/**
* dump all the threads, their info, and potential deadlocks.
*
* @param output
*/
public static void dumpThreads(String output)
{
try
{
PrintWriter pw = new PrintWriter(new FileWriter(output));
final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
final ThreadInfo[] threadInfos = threadMXBean.getThreadInfo(
threadMXBean.getAllThreadIds(), 100);
for (ThreadInfo threadInfo : threadInfos)
{
pw.println();
pw.println(threadInfo.getThreadName() + " ID:"
+ threadInfo.getThreadId());
Thread.State state = threadInfo.getThreadState();
pw.print(" java.lang.Thread.State: ");
pw.println(state);
pw.println(String.format("LockedMonitors : %s",
Arrays.toString(threadInfo.getLockedMonitors())));
pw.println(String.format("LockedSynchs : %s",
Arrays.toString(threadInfo.getLockedSynchronizers())));
pw.println(String.format("LockInfo : %s", threadInfo.getLockInfo()));
pw.println(String.format("LockName: %s LockOwner: %s [%d]",
threadInfo.getLockName(), threadInfo.getLockOwnerName(),
threadInfo.getLockOwnerId()));
pw.println();
StackTraceElement[] stackTraceElements = threadInfo.getStackTrace();
for (final StackTraceElement stackTraceElement : stackTraceElements)
{
pw.print(" ");
pw.println(stackTraceElement);
}
}
pw.println();
long[] dlt = threadMXBean.findDeadlockedThreads();
long[] mdlt = threadMXBean.findMonitorDeadlockedThreads();
pw.println(String.format("Deadlocked : %s", Arrays.toString(dlt)));
pw.println(String.format("MonitorDeadlocked : %s", Arrays.toString(mdlt)));
if (dlt == null && mdlt == null)
pw.println("Note: The lack of any deadlocked threads suggests a failed time update, perhaps from a simulation participant.");
pw.println();
pw.println("Clock information: ");
pw.println(ClockInterrogator.getAllClockDetails());
pw.println();
pw.println(LockUtilities.getLockInfo());
pw.flush();
pw.close();
}
catch (Exception e)
{
LOGGER.error("Failed to get thread dump ", e);
}
}
/**
* interrupts all the threads that we know of. This is horrible and will
* produce catastrophic errors, but can be useful in knowning where threads
* may have been locked.
*/
static public void interruptKnownThreads()
{
}
}