package tools;
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;
import org.apache.log4j.Logger;
public class DeadlockDetector extends Thread{
private static final Logger log = Logger.getLogger(DeadlockDetector.class);
private int checkInterval = 0;
private static final 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) {
log.error("检测到死锁!!");
this.sb = new StringBuilder();
noDeadLocks = false;
ThreadInfo[] infos = bean.getThreadInfo(threadIds);
this.sb.append("\n线程锁信息: \n");
for (ThreadInfo threadInfo : infos) {
printThreadInfo(threadInfo);
LockInfo[] lockInfos = threadInfo.getLockedSynchronizers();
MonitorInfo[] monitorInfos = threadInfo.getLockedMonitors();
printLockInfo(lockInfos);
printMonitorInfo(threadInfo, monitorInfos);
}
this.sb.append("\n线程转储: \n");
for (ThreadInfo ti : bean.dumpAllThreads(true, true)) {
printThreadInfo(ti);
}
log.error(this.sb.toString());
}
Thread.sleep(this.checkInterval);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
private void printThreadInfo(ThreadInfo threadInfo) {
printThread(threadInfo);
this.sb.append(INDENT).append(threadInfo.toString()).append("\n");
StackTraceElement[] stacktrace = threadInfo.getStackTrace();
MonitorInfo[] monitors = threadInfo.getLockedMonitors();
for (int i = 0; i < stacktrace.length; i++) {
StackTraceElement ste = stacktrace[i];
this.sb.append(INDENT).append("at ").append(ste.toString()).append("\n");
for (MonitorInfo mi : monitors) {
if (mi.getLockedStackDepth() == i) {
this.sb.append(INDENT).append(" - locked ").append(mi).append("\n");
}
}
}
}
private void printThread(ThreadInfo ti) {
this.sb.append("\nPrintThread\n");
this.sb.append("\"").append(ti.getThreadName()).append("\" Id=").append(ti.getThreadId()).append(" in ").append(ti.getThreadState()).append("\n");
if (ti.getLockName() != null) {
this.sb.append(" on lock=").append(ti.getLockName()).append("\n");
}
if (ti.isSuspended()) {
this.sb.append(" (suspended)\n");
}
if (ti.isInNative()) {
this.sb.append(" (running in native)\n");
}
if (ti.getLockOwnerName() != null) {
this.sb.append(INDENT).append(" owned by ").append(ti.getLockOwnerName()).append(" Id=").append(ti.getLockOwnerId()).append("\n");
}
}
private void printMonitorInfo(ThreadInfo threadInfo, MonitorInfo[] monitorInfos) {
this.sb.append(INDENT).append("Locked monitors: count = ").append(monitorInfos.length).append("\n");
for (MonitorInfo monitorInfo : monitorInfos) {
this.sb.append(INDENT).append(" - ").append(monitorInfo).append(" locked at \n");
this.sb.append(INDENT).append(" ").append(monitorInfo.getLockedStackDepth()).append(" ").append(monitorInfo.getLockedStackFrame()).append("\n");
}
}
private void printLockInfo(LockInfo[] lockInfos) {
this.sb.append(INDENT).append("Locked synchronizers: count = ").append(lockInfos.length).append("\n");
for (LockInfo lockInfo : lockInfos) {
this.sb.append(INDENT).append(" - ").append(lockInfo).append("\n");
}
}
}