Deadlock Detector
/*
* This file is part of aion-unique <aion-unique.org>.
*
* aion-unique is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* aion-unique 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with aion-unique. If not, see <http://www.gnu.org/licenses/>.
*/
//package com.aionemu.gameserver.utils;
import java.lang.management.LockInfo;
import java.lang.management.ManagementFactory;
import java.lang.management.MonitorInfo;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
/**
* @author ATracer
*/
public class DeadlockDetector implements Runnable
{
private int checkInterval = 0;
private static String INDENT = " ";
private StringBuilder sb = null;
public DeadlockDetector(int checkInterval)
{
this.checkInterval = checkInterval * 1000;
}
@Override
public void run()
{
boolean noDeadLocks = true;
while (noDeadLocks)
{
try
{
ThreadMXBean bean = ManagementFactory.getThreadMXBean();
long[] threadIds = bean.findDeadlockedThreads();
if (threadIds != null)
{
System.out.println("Deadlock detected!");
sb = new StringBuilder();
noDeadLocks = false;
ThreadInfo[] infos = bean.getThreadInfo(threadIds);
sb.append("\nTHREAD LOCK INFO: \n");
for (ThreadInfo threadInfo : infos)
{
printThreadInfo(threadInfo);
LockInfo[] lockInfos = threadInfo.getLockedSynchronizers();
MonitorInfo[] monitorInfos = threadInfo.getLockedMonitors();
printLockInfo(lockInfos);
printMonitorInfo(threadInfo, monitorInfos);
}
sb.append("\nTHREAD DUMPS: \n");
for (ThreadInfo ti : bean.dumpAllThreads(true, true))
{
printThreadInfo(ti);
}
System.out.println(sb.toString());
}
Thread.sleep(checkInterval);
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
private void printThreadInfo(ThreadInfo threadInfo)
{
printThread(threadInfo);
sb.append(INDENT + threadInfo.toString() + "\n");
StackTraceElement[] stacktrace = threadInfo.getStackTrace();
MonitorInfo[] monitors = threadInfo.getLockedMonitors();
for (int i = 0; i < stacktrace.length; i++)
{
StackTraceElement ste = stacktrace[i];
sb.append(INDENT + "at " + ste.toString() + "\n");
for (MonitorInfo mi : monitors)
{
if (mi.getLockedStackDepth() == i)
{
sb.append(INDENT + " - locked " + mi + "\n");
}
}
}
}
private void printThread(ThreadInfo ti)
{
sb.append("\nPrintThread\n");
sb.append("\"" + ti.getThreadName() + "\"" + " Id=" + ti.getThreadId() + " in " + ti.getThreadState() + "\n");
if (ti.getLockName() != null)
{
sb.append(" on lock=" + ti.getLockName() + "\n");
}
if (ti.isSuspended())
{
sb.append(" (suspended)" + "\n");
}
if (ti.isInNative())
{
sb.append(" (running in native)" + "\n");
}
if (ti.getLockOwnerName() != null)
{
sb.append(INDENT + " owned by " + ti.getLockOwnerName() + " Id=" + ti.getLockOwnerId() + "\n");
}
}
private void printMonitorInfo(ThreadInfo threadInfo, MonitorInfo[] monitorInfos)
{
sb.append(INDENT + "Locked monitors: count = " + monitorInfos.length + "\n");
for (MonitorInfo monitorInfo : monitorInfos)
{
sb.append(INDENT + " - " + monitorInfo + " locked at " + "\n");
sb.append(INDENT + " " + monitorInfo.getLockedStackDepth() + " " + monitorInfo.getLockedStackFrame() + "\n");
}
}
private void printLockInfo(LockInfo[] lockInfos)
{
sb.append(INDENT + "Locked synchronizers: count = " + lockInfos.length + "\n");
for (LockInfo lockInfo : lockInfos)
{
sb.append(INDENT + " - " + lockInfo + "\n");
}
}
}
Related examples in the same category