com.l2jfree.lang.L2Thread.java Source code

Java tutorial

Introduction

Here is the source code for com.l2jfree.lang.L2Thread.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.lang;

import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.lang.management.LockInfo;
import java.lang.management.ManagementFactory;
import java.lang.management.MonitorInfo;
import java.lang.management.ThreadInfo;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import javolution.util.FastList;

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

import com.l2jfree.util.concurrent.RunnableStatsManager;

/**
 * @author NB4L1
 */
public abstract class L2Thread extends Thread {
    private static final Log _log = LogFactory.getLog(L2Thread.class);

    protected L2Thread() {
        super();
    }

    protected L2Thread(String name) {
        super(name);
    }

    private volatile boolean _isAlive = true;

    public final void shutdown() throws InterruptedException {
        onShutdown();

        _isAlive = false;

        join();
    }

    protected void onShutdown() {
    }

    @Override
    public final void run() {
        try {
            while (_isAlive) {
                final long begin = System.nanoTime();

                try {
                    runTurn();
                } finally {
                    RunnableStatsManager.handleStats(getClass(), System.nanoTime() - begin);
                }

                try {
                    sleepTurn();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        } finally {
            onFinally();
        }
    }

    protected abstract void runTurn();

    protected abstract void sleepTurn() throws InterruptedException;

    protected void onFinally() {
    }

    public static List<String> getStats(Thread t) {
        List<String> list = new FastList<String>();

        list.add(t.toString() + " - ID: " + t.getId());
        list.add(" * State: " + t.getState());
        list.add(" * Alive: " + t.isAlive());
        list.add(" * Daemon: " + t.isDaemon());
        list.add(" * Interrupted: " + t.isInterrupted());
        for (ThreadInfo info : ManagementFactory.getThreadMXBean().getThreadInfo(new long[] { t.getId() }, true,
                true)) {
            for (MonitorInfo monitorInfo : info.getLockedMonitors()) {
                list.add("==========");
                list.add(" * Locked monitor: " + monitorInfo);
                list.add("\t[" + monitorInfo.getLockedStackDepth() + ".]: at " + monitorInfo.getLockedStackFrame());
            }

            for (LockInfo lockInfo : info.getLockedSynchronizers()) {
                list.add("==========");
                list.add(" * Locked synchronizer: " + lockInfo);
            }

            list.add("==========");
            for (StackTraceElement trace : info.getStackTrace())
                list.add("\tat " + trace);
        }

        return list;
    }

    public static List<String> getStats() {
        List<String> list = new FastList<String>();

        list.add(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z").format(new Date()));
        list.add("");
        list.add("## Java Platform Information ##");
        list.add("Java Runtime Name: " + System.getProperty("java.runtime.name"));
        list.add("Java Version: " + System.getProperty("java.version"));
        list.add("Java Class Version: " + System.getProperty("java.class.version"));
        list.add("");
        list.add("## Virtual Machine Information ##");
        list.add("VM Name: " + System.getProperty("java.vm.name"));
        list.add("VM Version: " + System.getProperty("java.vm.version"));
        list.add("VM Vendor: " + System.getProperty("java.vm.vendor"));
        list.add("VM Info: " + System.getProperty("java.vm.info"));
        list.add("");
        list.add("## OS Information ##");
        list.add("Name: " + System.getProperty("os.name"));
        list.add("Architeture: " + System.getProperty("os.arch"));
        list.add("Version: " + System.getProperty("os.version"));
        list.add("");
        list.add("## Runtime Information ##");
        list.add("CPU Count: " + Runtime.getRuntime().availableProcessors());
        list.add("");
        for (String line : getMemoryUsageStatistics())
            list.add(line);
        list.add("");
        list.add("## Class Path Information ##\n");
        for (String lib : System.getProperty("java.class.path").split(File.pathSeparator))
            if (!list.contains(lib))
                list.add(lib);
        list.add("");

        Set<Thread> threads = new TreeSet<Thread>(new Comparator<Thread>() {
            @Override
            public int compare(Thread t1, Thread t2) {
                if (t1.isDaemon() != t2.isDaemon())
                    return Boolean.valueOf(t1.isDaemon()).compareTo(t2.isDaemon());

                final StackTraceElement[] st1 = t1.getStackTrace();
                final StackTraceElement[] st2 = t2.getStackTrace();

                for (int i = 1;; i++) {
                    final int i1 = st1.length - i;
                    final int i2 = st2.length - i;

                    if (i1 < 0 || i2 < 0)
                        break;

                    final int compare = st1[i1].toString().compareToIgnoreCase(st2[i2].toString());

                    if (compare != 0)
                        return compare;
                }

                if (st1.length != st2.length)
                    return Integer.valueOf(st1.length).compareTo(st2.length);

                return Long.valueOf(t1.getId()).compareTo(t2.getId());
            }
        });
        threads.addAll(Thread.getAllStackTraces().keySet());
        list.add("## " + threads.size() + " thread(s) ##");
        list.add("=================================================");

        int i = 1;
        for (Thread thread : threads) {
            list.add("");
            list.add(i++ + ".");
            list.addAll(getStats(thread));
        }

        return list;
    }

    public static void dumpThreads() {
        PrintWriter pw = null;
        try {
            pw = new PrintWriter(new FileWriter("Thread-" + System.currentTimeMillis() + ".log"), true);

            for (String line : getStats())
                pw.println(line);
        } catch (Exception e) {
            _log.warn("", e);
        } finally {
            IOUtils.closeQuietly(pw);
        }
    }

    public static String[] getMemoryUsageStatistics() {
        double max = Runtime.getRuntime().maxMemory() / 1024; // maxMemory is the upper limit the jvm can use
        double allocated = Runtime.getRuntime().totalMemory() / 1024; //totalMemory the size of the current allocation pool
        double nonAllocated = max - allocated; //non allocated memory till jvm limit
        double cached = Runtime.getRuntime().freeMemory() / 1024; // freeMemory the unused memory in the allocation pool
        double used = allocated - cached; // really used memory
        double useable = max - used; //allocated, but non-used and non-allocated memory

        SimpleDateFormat sdf = new SimpleDateFormat("H:mm:ss");
        DecimalFormat df = new DecimalFormat(" (0.0000'%')");
        DecimalFormat df2 = new DecimalFormat(" # 'KB'");

        return new String[] { "+----", // ...
                "| Global Memory Informations at " + sdf.format(new Date()) + ":", // ...
                "|    |", // ...
                "| Allowed Memory:" + df2.format(max),
                "|    |= Allocated Memory:" + df2.format(allocated) + df.format(allocated / max * 100),
                "|    |= Non-Allocated Memory:" + df2.format(nonAllocated) + df.format(nonAllocated / max * 100),
                "| Allocated Memory:" + df2.format(allocated),
                "|    |= Used Memory:" + df2.format(used) + df.format(used / max * 100),
                "|    |= Unused (cached) Memory:" + df2.format(cached) + df.format(cached / max * 100),
                "| Useable Memory:" + df2.format(useable) + df.format(useable / max * 100), // ...
                "+----" };
    }
}