com.l2jfree.gameserver.threadmanager.DeadlockDetector.java Source code

Java tutorial

Introduction

Here is the source code for com.l2jfree.gameserver.threadmanager.DeadlockDetector.java

Source

/*
 * This program 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.
 * 
 * This program 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
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */
package com.l2jfree.gameserver.threadmanager;

import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javolution.util.FastSet;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.l2jfree.Config;
import com.l2jfree.gameserver.Shutdown;
import com.l2jfree.gameserver.Shutdown.ShutdownMode;
import com.l2jfree.gameserver.util.Util;
import com.l2jfree.lang.L2Thread;

public final class DeadlockDetector extends L2Thread {
    private static final Log _log = LogFactory.getLog(DeadlockDetector.class);

    private static final class SingletonHolder {
        private static final DeadlockDetector INSTANCE = new DeadlockDetector();
    }

    public static DeadlockDetector getInstance() {
        return SingletonHolder.INSTANCE;
    }

    private final Set<Long> _logged = new FastSet<Long>();

    private DeadlockDetector() {
        super("DeadlockDetector");
        setPriority(Thread.MAX_PRIORITY);
        setDaemon(true);

        start();

        _log.info("DeadlockDetector: Initialized.");
    }

    @Override
    protected void runTurn() {
        long[] ids = findDeadlockedThreadIds();
        if (ids == null)
            return;

        List<Thread> deadlocked = new ArrayList<Thread>();

        for (long id : ids)
            if (_logged.add(id))
                deadlocked.add(findThreadById(id));

        if (!deadlocked.isEmpty()) {
            Util.printSection("Deadlocked Thread(s)");
            for (Thread thread : deadlocked) {
                _log.fatal("");

                for (String line : L2Thread.getStats(thread))
                    _log.fatal(line);
            }

            new Halt().start();

            Shutdown.start("DeadlockDetector", 1, ShutdownMode.RESTART);
        }
    }

    @Override
    protected void sleepTurn() throws InterruptedException {
        Thread.sleep(Config.DEADLOCKCHECK_INTERVAL);
    }

    private long[] findDeadlockedThreadIds() {
        if (ManagementFactory.getThreadMXBean().isSynchronizerUsageSupported())
            return ManagementFactory.getThreadMXBean().findDeadlockedThreads();
        else
            return ManagementFactory.getThreadMXBean().findMonitorDeadlockedThreads();
    }

    private Thread findThreadById(long id) {
        for (Thread thread : Thread.getAllStackTraces().keySet())
            if (thread.getId() == id)
                return thread;

        throw new IllegalStateException("Deadlocked Thread not found!");
    }

    private static final class Halt extends Thread {
        @Override
        public void run() {
            try {
                sleep(40000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                Shutdown.halt("DeadlockDetector");
            }
        }
    }
}