/ Java EE Support Patterns

7.05.2012

How to analyze Thread Dump – Part 5: Thread Stack Trace

This article is part 5 of our Thread Dump analysis series. So far you have learned the basic principles of threads and their interactions with your Java EE container & JVM. You have also learned different Thread Dump formats for HotSpot and IBM Java VM’s. It is now time for you to deep dive into the analysis process.

** UPDATE: Thread Dump analysis tutorial videos now available here.

In order for you to quickly identify a problem pattern from a Thread Dump, you first need to understand how to read a Thread Stack Trace and how to get the “story” right. This means that if I ask you to tell me what the Thread #38 is doing; you should be able to precisely answer; including if Thread Stack Trace is showing a healthy (normal) vs. hang condition.

Java Stack Trace revisited

Most of you are familiar with Java stack traces. This is typical data that we find from server and application log files when a Java Exception is thrown. In this context, a Java stack trace is giving us the code execution path of the Thread that triggered the Java Exception such as a java.lang.NoClassDefFoundError, java.lang.NullPpointerException etc. Such code execution path allows us to see the different layers of code that ultimately lead to the Java Exception.

Java stack traces must always be read from bottom-up:
-        The line at the bottom will expose the originator of the request such as a Java / Java EE container Thread.
-        The first line at the top of the stack trace will show you the Java class where that last Exception got triggered.

Let’s go through this process via a simple example. We created a sample Java program simply executing some Class methods calls and throwing an Exception. The program output generated is as per below:

JavaStrackTraceSimulator
Author: Pierre-Hugues Charbonneau

Exception in thread "main" java.lang.IllegalArgumentException:
        at org.ph.javaee.training.td.Class2.call(Class2.java:12)
        at org.ph.javaee.training.td.Class1.call(Class1.java:14)
        at org.ph.javaee.training.td.JavaSTSimulator.main(JavaSTSimulator.java:20)

-        Java program JavaSTSimulator is invoked (via the “main” Thread)
-        The simulator then invokes method call() from Class1
-        Class1 method call() then invokes Class2 method call()
-        Class2 method call()throws a Java Exception: java.lang.IllegalArgumentException
-        The Java Exception is then displayed in the log / standard output

As you can see, the code execution path that lead to this Exception is always displayed from bottom-up.

The above analysis process should be well known for any Java programmer. What you will see next is that the Thread Dump Thread stack trace analysis process is very similar to above Java stack trace analysis.

Thread Dump: Thread Stack Trace analysis

Thread Dump generated from the JVM provides you with a code level execution snapshot of all the “created” Threads of the entire JVM process. Created Threads does not mean that all these Threads are actually doing something. In a typical Thread Dump snapshot generated from a Java EE container JVM:

-        Some Threads could be performing raw computing tasks such as XML parsing, IO / disk access etc.
-        Some Threads could be waiting for some blocking IO calls such as a remote Web Service call, a DB / JDBC query etc.
-        Some Threads could be involved in garbage collection at that time e.g. GC Threads
-        Some Threads will be waiting for some work to do (Threads not doing any work typically go in wait() state)
-        Some Threads could be waiting for some other Threads work to complete e.g. Threads waiting to acquire a monitor lock (synchronized block{}) on some objects

I will get back to the above with more diagrams in my next article but for now let’s focus on the stack trace analysis process. Your next task is to be able to read a Thread stack trace and understand what it is doing, on the best of your knowledge.

A Thread stack trace provides you with a snapshot of its current execution. The first line typically includes native information of the Thread such as its name, state, address etc. The current execution stack trace has to be read from bottom-up. Please follow the analysis process below. The more experience you get with Thread Dump analysis, the faster you will able to read and identify very quickly the work performed by each Thread:

-        Start to read the Thread stack trace from the bottom
-        First, identify the originator (Java EE container Thread, custom Thread ,GC Thread, JVM internal Thread, standalone Java program “main” Thread etc.)
-        The next step is to identify the type of request the Thread is executing (WebApp, Web Service, JMS, Remote EJB (RMI), internal Java EE container etc.)
-        The next step is to identify form the execution stack trace your application module(s) involved e.g. the actual core work the Thread is trying to perform. The complexity of analysis will depend of the layers of abstraction of your middleware environment and application
-        The next step is to look at the last ~10-20 lines prior to the first line. Identify the protocol or work the Thread is involved with e.g. HTTP call, Socket communication, JDBC or raw computing tasks such as disk access, class loading etc.
-        The next step is to look at the first line. The first line usually tells a LOT on the Thread state since it is the current piece of code executed at the time you took the snapshot
-        The combination of the last 2 steps is what will give you the core of information to conclude of what work and / or hanging condition the Thread is involved with

Now find below a visual breakdown of the above steps using a real example of a Thread Dump Thread stack trace captured from a JBoss 5 production environment. In this example, many Threads were showing a similar problem pattern of excessive IO when creating new instances of JAX-WS Service instances.


As you can see, the last 10 lines along with the first line will tell us what hanging or slow condition the Thread is involved with, if any. The lines from the bottom will give us detail of the originator and type of request.

I hope this article has helped you understand the importance of proper Thread stack trace analysis. I will get back with much more Thread stack trace examples when we cover the most common Thread Dump problem patterns in future articles. The next article will now teach you how to breakdown the Thread Dump threads in logical silos and come up with a potential list of root cause “suspects”.

Please feel free to post any comment and question.

6.20.2012

Top 10 Java EE performance problems

Performance problems are one of the biggest challenges to expect when designing and implementing Java EE related technologies. Some of these common problems can be faced when implementing either lightweight or large IT environments; which typically include several distributed systems from Web portals & ordering applications to enterprise service bus (ESB), data warehouse and legacy Mainframe storage systems.

It is very important for IT architects and Java EE developers to understand their client environments and ensure that the proposed solutions will not only meet their growing business needs but also ensure a long term scalable & reliable production IT environment; and at the lowest cost possible. Performance problems can disrupt your client business which can result in short & long term loss of revenue.

This article will consolidate and share the top 10 causes of Java EE performance problems I have encountered working with IT & Telecom clients over the last 10 years along with high level recommendations.

>>>>>>> The full article is available at DZone: Top 10 Causes of Java EE Enterprise Performance Problems

6.15.2012

java.lang.NoClassDefFoundError: How to resolve – Part 2

This article is part 2 of our java.lang.NoClassDefFoundError troubleshooting series. It will focus on the more simple type of NoClassDefFoundError problem. This article is ideal for Java beginners and I highly recommend that you compile, run and study the sample Java program.
If not done already, I suggest that you first review the java.lang.NoClassDefFoundError - Part 1.

The following writing format will be used going forward and will provide you with:

-        Description of the problem case and type of NoClassDefFoundError.
-        Sample Java program “simulating” the problem case.
-        ClassLoader chain view.
-        Recommendations and resolution strategies.

NoClassDefFoundError problem case 1 – missing JAR file

The first problem case we will cover is related to a Java program packaging and / or classpath problem. A typical Java program can include one or many JAR files created at compile time. NoClassDefFoundError can often be observed when you forget to add JAR file(s) containing Java classes referenced by your Java or Java EE application.

This type of problem is normally not hard to resolve once you analyze the Java Exception and missing Java class name.

Sample Java program
The following simple Java program is split as per below:

-        The main Java program NoClassDefFoundErrorSimulator
-        The caller Java class CallerClassA
-        The referencing Java class ReferencingClassA
-        A util class for ClassLoader and logging related facilities JavaEETrainingUtil

This program is simple attempting to create a new instance and execute a method of the Java class CallerClassA which is referencing the class ReferencingClassA.It will demonstrate how a simple classpath problem can trigger NoClassDefFoundError. The program is also displaying detail on the current class loader chain at class loading time in order to help you keep track of this process. This will be especially useful for future and more complex problem cases when dealing with larger class loader chains.

#### NoClassDefFoundErrorSimulator.java
package org.ph.javaee.training1;

import org.ph.javaee.training.util.JavaEETrainingUtil;

/**
 * NoClassDefFoundErrorTraining1
 * @author Pierre-Hugues Charbonneau
 *
 */
public class NoClassDefFoundErrorSimulator {
       
       
        /**
         * @param args
         */
        public static void main(String[] args) {
               System.out.println("java.lang.NoClassDefFoundError Simulator - Training 1");
               System.out.println("Author: Pierre-Hugues Charbonneau");
               System.out.println("http://javaeesupportpatterns.blogspot.com");
              
               // Print current Classloader context
               System.out.println("\nCurrent ClassLoader chain: "+JavaEETrainingUtil.getCurrentClassloaderDetail());
              
               // 1. Create a new instance of CallerClassA
               CallerClassA caller = new CallerClassA();
              
               // 2. Execute method of the caller
               caller.doSomething();
              
               System.out.println("done!");
        }
}


#### CallerClassA.java
package org.ph.javaee.training1;

import org.ph.javaee.training.util.JavaEETrainingUtil;

/**
 * CallerClassA
 * @author Pierre-Hugues Charbonneau
 *
 */
public class CallerClassA {
       
        private final static String CLAZZ = CallerClassA.class.getName();
       
        static {
               System.out.println("Classloading of "+CLAZZ+" in progress..."+JavaEETrainingUtil.getCurrentClassloaderDetail());
        }
       
        public CallerClassA() {
               System.out.println("Creating a new instance of "+CallerClassA.class.getName()+"...");
        }
       
        public void doSomething() {
              
               // Create a new instance of ReferencingClassA
               ReferencingClassA referencingClass = new ReferencingClassA();             
        }
}

#### ReferencingClassA.java
package org.ph.javaee.training1;

import org.ph.javaee.training.util.JavaEETrainingUtil;

/**
 * ReferencingClassA
 * @author Pierre-Hugues Charbonneau
 *
 */
public class ReferencingClassA {

        private final static String CLAZZ = ReferencingClassA.class.getName();
       
        static {
               System.out.println("Classloading of "+CLAZZ+" in progress..."+JavaEETrainingUtil.getCurrentClassloaderDetail());
        }
       
        public ReferencingClassA() {
               System.out.println("Creating a new instance of "+ReferencingClassA.class.getName()+"...");
        }
       
        public void doSomething() {
               //nothing to do...
        }
}


#### JavaEETrainingUtil.java
package org.ph.javaee.training.util;

import java.util.Stack;
import java.lang.ClassLoader;

/**
 * JavaEETrainingUtil
 * @author Pierre-Hugues Charbonneau
 *
 */
public class JavaEETrainingUtil {
       
        /**
         * getCurrentClassloaderDetail
         * @return
         */
        public static String getCurrentClassloaderDetail() {
              
               StringBuffer classLoaderDetail = new StringBuffer();       
               Stack<ClassLoader> classLoaderStack = new Stack<ClassLoader>();
              
               ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
              
               classLoaderDetail.append("\n-----------------------------------------------------------------\n");
              
               // Build a Stack of the current ClassLoader chain
               while (currentClassLoader != null) {
              
                       classLoaderStack.push(currentClassLoader);
                      
                       currentClassLoader = currentClassLoader.getParent();
               }
              
               // Print ClassLoader parent chain
               while(classLoaderStack.size() > 0) {
                      
                       ClassLoader classLoader = classLoaderStack.pop();
                      
                       // Print current                     
                       classLoaderDetail.append(classLoader);
                      
                       if (classLoaderStack.size() > 0) {
                              classLoaderDetail.append("\n--- delegation ---\n");                               
                       } else {
                              classLoaderDetail.append(" **Current ClassLoader**");
                       }
               }
              
               classLoaderDetail.append("\n-----------------------------------------------------------------\n");
              
               return classLoaderDetail.toString();
        }
}


Problem reproduction

In order to replicate the problem, we will simply “voluntary” omit one of the JAR files from the classpath that contains the referencing Java class ReferencingClassA.

The Java program is packaged as per below:

-        MainProgram.jar (contains NoClassDefFoundErrorSimulator.class and JavaEETrainingUtil.class)
-        CallerClassA.jar (contains CallerClassA.class)
-        ReferencingClassA.jar (contains ReferencingClassA.class)

Now, let’s run the program as is:

## Baseline (normal execution)
..\bin>java -classpath CallerClassA.jar;ReferencingClassA.jar;MainProgram.jar org.ph.javaee.training1.NoClassDefFoundErrorSimulator

java.lang.NoClassDefFoundError Simulator - Training 1
Author: Pierre-Hugues Charbonneau
http://javaeesupportpatterns.blogspot.com

Current ClassLoader chain:
-----------------------------------------------------------------
sun.misc.Launcher$ExtClassLoader@17c1e333
--- delegation ---
sun.misc.Launcher$AppClassLoader@214c4ac9 **Current ClassLoader**
-----------------------------------------------------------------

Classloading of org.ph.javaee.training1.CallerClassA in progress...
-----------------------------------------------------------------
sun.misc.Launcher$ExtClassLoader@17c1e333
--- delegation ---
sun.misc.Launcher$AppClassLoader@214c4ac9 **Current ClassLoader**
-----------------------------------------------------------------

Creating a new instance of org.ph.javaee.training1.CallerClassA...
Classloading of org.ph.javaee.training1.ReferencingClassA in progress...
-----------------------------------------------------------------
sun.misc.Launcher$ExtClassLoader@17c1e333
--- delegation ---
sun.misc.Launcher$AppClassLoader@214c4ac9 **Current ClassLoader**
-----------------------------------------------------------------

Creating a new instance of org.ph.javaee.training1.ReferencingClassA...
done!


For the initial run (baseline), the main program was able to create a new instance of CallerClassA and execute its method successfully; including successful class loading of the referencing class ReferencingClassA.

## Problem reproduction run (with removal of ReferencingClassA.jar)
../bin>java -classpath CallerClassA.jar;MainProgram.jar org.ph.javaee.training1.NoClassDefFoundErrorSimulator

java.lang.NoClassDefFoundError Simulator - Training 1
Author: Pierre-Hugues Charbonneau
http://javaeesupportpatterns.blogspot.com

Current ClassLoader chain:
-----------------------------------------------------------------
sun.misc.Launcher$ExtClassLoader@17c1e333
--- delegation ---
sun.misc.Launcher$AppClassLoader@214c4ac9 **Current ClassLoader**
-----------------------------------------------------------------

Classloading of org.ph.javaee.training1.CallerClassA in progress...
-----------------------------------------------------------------
sun.misc.Launcher$ExtClassLoader@17c1e333
--- delegation ---
sun.misc.Launcher$AppClassLoader@214c4ac9 **Current ClassLoader**
-----------------------------------------------------------------

Creating a new instance of org.ph.javaee.training1.CallerClassA...
Exception in thread "main" java.lang.NoClassDefFoundError: org/ph/javaee/training1/ReferencingClassA
        at org.ph.javaee.training1.CallerClassA.doSomething(CallerClassA.java:25)
        at org.ph.javaee.training1.NoClassDefFoundErrorSimulator.main(NoClassDefFoundErrorSimulator.java:28)
Caused by: java.lang.ClassNotFoundException: org.ph.javaee.training1.ReferencingClassA
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        ... 2 more


What happened? The removal of the ReferencingClassA.jar, containing ReferencingClassA, did prevent the current class loader to locate this referencing Java class at runtime leading to ClassNotFoundException and NoClassDefFoundError.

This is the typical Exception that you will get if you omit JAR file(s) from your Java start-up classpath or within an EAR / WAR for Java EE related applications.

ClassLoader view

Now let’s review the ClassLoader chain so you can properly understand this problem case. As you saw from the Java program output logging, the following Java ClassLoaders were found:

Classloading of org.ph.javaee.training1.CallerClassA in progress...
-----------------------------------------------------------------
sun.misc.Launcher$ExtClassLoader@17c1e333
--- delegation ---
sun.misc.Launcher$AppClassLoader@214c4ac9 **Current ClassLoader**
-----------------------------------------------------------------

** Please note that the Java bootstrap class loader is responsible to load the core JDK classes and is written in native code **

## sun.misc.Launcher$AppClassLoader
This is the system class loader responsible to load our application code found from the Java classpath specified at start-up.

##sun.misc.Launcher$ExtClassLoader
This is the extension class loader responsible to load code in the extensions directories (<JAVA_HOME>/lib/ext, or any other directory specified by the java.ext.dirs system property).

As you can see from the Java program logging output, the extension class loader is the actual super parent of the system class loader. Our sample Java program was loaded at the system class loader level. Please note that this class loader chain is very simple for this problem case since we did not create child class loaders at this point. This will be covered in future articles.

Recommendations and resolution strategies

Now find below my recommendations and resolution strategies for NoClassDefFoundError problem case 1:

-        Review the java.lang.NoClassDefFoundError error and identify the missing Java class
-        Verify and locate the missing Java class from your compile / build environment
-        Determine if the missing Java class is from your application code, third part API or even the Java EE container itself. Verify where the missing JAR file(s) is / are expected to be found
-        Once found, verify your runtime environment Java classpath for any typo or missing JAR file(s)
-        If the problem is triggered from a Java EE application, perform the same above steps but verify the packaging of your EAR / WAR file for missing JAR and other library file dependencies such as MANIFEST

Please feel free to post any question or comment. The part 3 is now available.