Thread Dump JSP

I was trying to google first and found some implementations:

unfortunately, no one displays lock information properly, so I wrote my own.

<%@ page import="java.io.IOException" %>
<%@ page import="java.io.PrintWriter" %>
<%@ page import="java.lang.management.LockInfo" %>
<%@ page import="java.lang.management.ManagementFactory" %>
<%@ page import="java.lang.management.MonitorInfo" %>
<%@ page import="java.lang.management.ThreadInfo" %>
<%@ page import="java.lang.management.ThreadMXBean" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.Collections" %>
<%@ page import="java.util.List" %>

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<%!
    public class MyThreadInfo implements Comparable<MyThreadInfo> {

        private final long threadID;

        private final ThreadInfo threadInfo;

        private final String name;

        public MyThreadInfo(ThreadInfo info) {
            threadInfo = info;
            name = info.getThreadName();
            threadID = info.getThreadId();
        }

        public int compareTo(MyThreadInfo o) {
            String myName = name + threadID;
            String yourName = o.name + o.threadID;
            return myName.compareTo(yourName);
        }

    }

    public List<MyThreadInfo> getThreads(boolean deadlock) {
        ThreadMXBean tmb = ManagementFactory.getThreadMXBean();
        ArrayList<MyThreadInfo> threads = new ArrayList<MyThreadInfo>();
        long[] threadIds = null;
        if (deadlock) {
            threadIds = tmb.findDeadlockedThreads();
        } else {
            threadIds = tmb.getAllThreadIds();
        }
        if (threadIds == null) {
            return Collections.emptyList();
        }
        for (ThreadInfo info : tmb.getThreadInfo(threadIds, true, true)) {
            if (info != null) {
                threads.add(new MyThreadInfo(info));
            }

        }
        Collections.sort(threads);
        return threads;
    }

    public String toString(ThreadInfo threadInfo) {
        StringBuilder sb = new StringBuilder("\"" + threadInfo.getThreadName() + "\"" +
                " Id=" + threadInfo.getThreadId() + " " +
                threadInfo.getThreadState());
        if (threadInfo.getLockName() != null) {
            sb.append(" on ").append(threadInfo.getLockName());
        }
        if (threadInfo.getLockOwnerName() != null) {
            sb.append(" owned by \"").append(threadInfo.getLockOwnerName())
                    .append("\" Id=").append(threadInfo.getLockOwnerId());
        }
        if (threadInfo.isSuspended()) {
            sb.append(" (suspended)");
        }
        if (threadInfo.isInNative()) {
            sb.append(" (in native)");
        }
        sb.append('\n');
        StackTraceElement[] stackTrace = threadInfo.getStackTrace();
        for (int i = 0, n = stackTrace.length; i < n; i++) {
            StackTraceElement ste = stackTrace[i];
            sb.append("\tat ").append(ste.toString());
            sb.append('\n');
            if (i == 0 && threadInfo.getLockInfo() != null) {
                Thread.State ts = threadInfo.getThreadState();
                switch (ts) {
                    case BLOCKED:
                        sb.append("\t-  blocked on ").append(threadInfo.getLockInfo());
                        sb.append('\n');
                        break;
                    case WAITING:
                        sb.append("\t-  waiting on ").append(threadInfo.getLockInfo());
                        sb.append('\n');
                        break;
                    case TIMED_WAITING:
                        sb.append("\t-  waiting on ").append(threadInfo.getLockInfo());
                        sb.append('\n');
                        break;
                    default:
                }
            }

            for (MonitorInfo mi : threadInfo.getLockedMonitors()) {
                if (mi.getLockedStackDepth() == i) {
                    sb.append("\t-  locked ").append(mi);
                    sb.append('\n');
                }
            }
        }

        LockInfo[] locks = threadInfo.getLockedSynchronizers();
        if (locks.length > 0) {
            sb.append("\n\tNumber of locked synchronizers = ").append(locks.length);
            sb.append('\n');
            for (LockInfo li : locks) {
                sb.append("\t- ").append(li);
                sb.append('\n');
            }
        }
        sb.append('\n');
        return sb.toString();
    }

    public void printThreads(List<MyThreadInfo> threads, JspWriter out) throws IOException {
        out.println("<br><b>Total threads: " + threads.size() + "</b>");
        for (MyThreadInfo mti : threads) {
            out.println("<pre>");
            out.print(toString(mti.threadInfo));
            out.println("</pre>");
        }
    }

%>
<html>
<body>
<table>
    <tr>
        <td><b>Date:</b></td>
        <td><%=new java.util.Date()%>
        </td>
    </tr>
</table>

<%
    try {
        printThreads(getThreads(false), out);
        List<MyThreadInfo> deadLockedThreads = getThreads(true);
        if (deadLockedThreads != null && !deadLockedThreads.isEmpty()) {
            out.print("<br><b>Found deadlocks:<b>");
            printThreads(deadLockedThreads, out);
        }
    } catch (Exception e) {
        out.print("<pre>");
        e.printStackTrace(new PrintWriter(out, true));
        out.print("</pre>");
    }
%>
</body>
</html>

One thought on “Thread Dump JSP

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s