|
The Java Specialists' Newsletter
Issue 132 2006-09-11
Category:
Tips and Tricks
Java version: JDK 1.5 Thread Dump JSP in Java 5by Dr. Heinz M. KabutzAbstract:
Sometimes it is useful to have a look at what the threads are
doing in a light weight fashion in order to discover tricky
bugs and bottlenecks. Ideally this should not disturb the
performance of the running system. In addition, it should be
universally usable and cost nothing. Have a look at how we do
it in this newsletter.
Welcome to the 132nd edition of The Java(tm) Specialists' Newsletter. I am sitting about
30000 feet above the Norwegian Sea on route to Oslo for what is
said to be one of the finest Java conferences. JavaZone is put
together by the javaBin JUG in Norway. Apparently all the
Java companies in Norway shut down this week. Imagine 2 days,
and almost 100 talks to attend! These Norwegians show no mercy,
in line with their Viking ancestry, and have even scheduled
talks during lunch time :-)
Thanks for all the kind wishes for the
birth
of our daughter, Evangeline Kineta Kabutz. She has
only woken me up twice in the last six weeks. She is growing
beautifully and will have a tough lean frame like her brother.
Upcoming Java Specialist Master Courses:
- please click here to sign up.
As from May 2010, we are also offering this course on the island of Crete. We
only accept 6 students per class in Crete, due to the size of our conference
room. Please book early to avoid disappointment!
San Jose CA, Mar 16-19 2010, $3500 Ottawa, Canada, Mar 22-25 2010, $3500 Oslo, Norway, Apr 13-16 2010, Kr 24500 Montreal, Canada, Apr 20-23 2010, $3500 Toronto, Canada, May 17-20 2010, $3500 Chania, Crete, May 25-28, Jun 29-Jul 2 or Aug 24-27 2010, €2500
In-house courses if these dates or locations do not suit you - click here for more information. Thread Dump JSP in Java 5
Ten days ago, I received a desperate phone call from a large
company in Cape Town. Their Java system tended to become
unstable after some time, and especially during peak periods.
Since the users were processing millions of dollars on this
system, they should be able to log in at any time.
We managed to solve their problem. As you probably guessed, it
was due to incorrectly handled concurrency. I cannot divulge how
we find such problems or how to fix it, that is our competitive
advantage. Contact me
offlist if your company has bugs or performance
issues that you cannot solve and where an extra pair of eyes can
be useful.
One of the measurements we looked at was to inspect what the
threads were doing. In this case, it did not reveal much, but
it can be of great value in finding other issues. For example,
at another customer, we stumbled upon an infinite loop by
looking at what the threads were up to.
There are several ways of doing that. If you are using Unix,
you can send a "kill -3" to the process. With Windows,
CTRL+Break on the console will give you that information.
This server was running on Windows (don't laugh). The
application server did not allow us to start the JVM in a
console window, which meant that we could not press CTRL+Break.
Another approach would have been to painstakingly step through
the threads with JConsole. That was not an option to me.
One of the annoying parts of the typical thread dump is that the
threads are not sorted, so it becomes a bit tricky to group
them. It would also be nice to see a summary of the state in
a table, to make it easier to find problems. In addition, we
should be able to copy the text and diff it to see how things
change between refreshes.
In good OO fashion, we separate model and view. Let's first
define the model:
package com.cretesoft.tjsn.performance;
import java.io.Serializable;
import java.util.*;
public class ThreadDumpBean implements Serializable {
private final Map<Thread, StackTraceElement[]> traces;
public ThreadDumpBean() {
traces = new TreeMap<Thread, StackTraceElement[]>(THREAD_COMP);
traces.putAll(Thread.getAllStackTraces());
}
public Collection<Thread> getThreads() {
return traces.keySet();
}
public Map<Thread, StackTraceElement[]> getTraces() {
return traces;
}
/**
* Compare the threads by name and id.
*/
private static final Comparator<Thread> THREAD_COMP =
new Comparator<Thread>() {
public int compare(Thread o1, Thread o2) {
int result = o1.getName().compareTo(o2.getName());
if (result == 0) {
Long id1 = o1.getId();
Long id2 = o2.getId();
return id1.compareTo(id2);
}
return result;
}
};
}
We also write a bit of JSP, making use of the Expression
Language ${}.
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<jsp:useBean id="threadDump"
class="com.cretesoft.tjsn.performance.ThreadDumpBean"
scope="request"/>
<HTML>
<BODY>
<h2>Thread Summary:</h2>
<table cellpadding="5" cellspacing="5">
<tr>
<th>Thread</th>
<th>State</th>
<th>Priority</th>
<th>Daemon</th>
</tr>
<c:forEach items="${threadDump.threads}" var="thr">
<tr>
<td><a href="#${thr.id}">${thr.name}</a></td>
<td>${thr.state}</td>
<td>${thr.priority}</td>
<td>${thr.daemon}</td>
</tr>
</c:forEach>
</table>
<h2>Stack Trace of JVM:</h2>
<c:forEach items="${threadDump.traces}" var="trace">
<h4><a name="${trace.key.id}">${trace.key}</a></h4>
<pre>
<c:forEach items="${trace.value}" var="traceline">
at ${traceline}</c:forEach>
</pre>
</c:forEach>
</BODY>
</HTML>
This will generate first a summary of the threads with
hyperlinks to the individual stack traces. The summary shows
the state of each thread.
A word of warning: you should not make this JSP page publicly
accessible on your server, as it opens up the guts of the app
server to the general population. Even if they cannot change
the state of the threads, it might be bad enough for them to
see what methods are being executed.
You might have to change the GET_STACK_TRACE_PERMISSION setting
to allow yourself access into the application server.
This is a took that I will keep handy whenever I do performance
tuning or difficult bug fixing on a J2EE server running Java 5.
I look forward to hearing from you how you expanded this idea to
make it even more useful :)
Kind regards
Heinz
Tips and Tricks Articles
Related Java Course
|