DeadlockDetector.java Source code

Java tutorial

Introduction

Here is the source code for DeadlockDetector.java

Source

/*
 * 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");
        }
    }
}