Skip to main content

The Taming of the Stack Trace

Posted by synodinos on August 16, 2007 at 3:03 PM PDT

shakespeare.jpgOne concept of Java development that is intimidating to fresh developers and a mystery to funs of other languages is the Stack Trace (ST). There is little available documentation out there and most of the times a useful ST can be very long and verbose.

The public was familiarized with the ST from poorly developed and configured web applications that used to spit out their internal state for every little error they encountered. For example you can find yourself a variety of Tomcat hosted broken web apps that print out a ST just by googling for it. These might range from a simple “Too many connections” error to broken installations and more.

But what is actually a Java Stack Trace..?

Basically it is a snapshot of the all threads and monitors in a JVM. Depending on how complex your application is a ST can range from a few lines to thousands of lines of diagnostics. Regardless of the size the ST is one of the most valuable diagnostics tool you can have as a Java developer. It cannot be substituted by the output generated by java.util.logging or Log4J since these cannot show thread dumps.

How can I get a Stack Trace?

Essentially you can get a ST either by:

  • Working with your operating system,
  • Programmatically from within the code or
  • Outside of the JVM with JMX

On UNIX platforms you can send a signal to a program by using the kill command. This is the quit signal (signal 3 - SIGQUIT) which is handled by the JVM. A signal is a message which can be sent to a running process and each Unix signal has a default set of effects on a program. Programmers can code their applications to respond in customized ways to most signals and these custom pieces of code are called signal handlers.

For example you can use the command:

kill -3  process_id, or
kill -QUIT  process_id,

where process_id is the process number of your Java program.

As far as I know in order to get this on Windows you must be at the console with command prompt window running the application and press +Break.

Programmatically you can generate a partial Java stack trace, which in this case is only the threads information, by using getStackTrace() or printStackTrace() of the Throwable class.

Sometimes it is necessary to generate a ST remotely or without disrupting the application. One of the mechanisms to control ST generation from outside the JVM uses RMI. Just create a remote interface, register the ST generator with the rmiregistry and call it using a RMI client. The J2SE since version 5 provides the management and monitoring APIs that use JMX as the underlying mechanism to expose the JVM information. The use of JMX allows the information to be available locally and remotely to applications that support JMX.

Of course you can get a ST if the JVM experiences an internal error. As in the case of the broken web apps mentioned earlier, it will call its own signal handler to print out the threads information.

Where can I find it?

Sometimes the ST is a bit tricky to find. There are several start up scripts out there that choose to redirect the console to /dev/null or some file.

For example this is part of a JBoss start up script that would send your ST to /dev/null:

#  description: JBoss Application Server Start-Up Script
#define  what will be done with the console log
#  JBOSS_CONSOLE=/dev/tty9
if [ -n  "$JBOSS_CONSOLE" -a ! -d "$JBOSS_CONSOLE" ]; then
if [ -n "$SUBIT" ]; then
#if [ -n  "$JBOSS_CONSOLE" ] && [ -e "$JBOSS_CONSOLE" ]; then
#  echo "WARNING: location for saving  console log invalid: $JBOSS_CONSOLE"
#  echo "WARNING: ignoring it and using  /dev/null"
#  JBOSS_CONSOLE="/dev/null"

As for your own application, Java gives you the choice of directing program messages to the system console, but error messages, say to a file. The class System has a variable out that represents the standard output, and the variable err that represents the standard error device. By default, they both point at the system console. This shows how the standard error output could be re-directed:

Stream st =  new Stream(new FileOutputStream("output.txt")); 

So what can the Stack Trace tell me?

There are several pieces of useful information that the ST can provide you with. Here are some examples:

  • Find the current thread: In theory the current thread should be the last thread that was running when the snapshot was taken. If you have seen a ST before you may have noticed that often the current thread is labeled “current thread” next to the appropriate thread. Of course this is only a good guess by the signal handler and sometimes the signal handler will be marked as the current thread or on some platforms none of the threads will be marked as the current thread.
  • Determine the thread states: You will see many different threads in many different states in a snapshot from a ST – running, suspended, waiting etc. This will help you resolve the execution state of your application.
  • Locate deadlocks: If your program is in a deadlock then some of the system threads will probably show up as the current threads, because there is nothing else for the JVM to do.
  • Find why teh program hangs: Knowing the state of the threads you can see which ones are waiting (states MW or CW). This is especially valuable for debugging distributed applications or applications which open socket and have to deal with network time-outs.
  • Debug third-party applications: If you don’t have access to the source code, examining the ST can give you a good insight of how the application is working or why it is not :-)

Isn’t it sometimes… TOO verbose..?!?

Yes a ST, can get pretty verbose and this has been discussed by people in great length but this is partially due to the fact that Java applications use all kinds of abstraction and components. Abstractions are good: if it weren’t for the abstraction of the OSI Network Model you wouldn’t be seeing this web page.

Related Topics >>