/ January 2012 ~ Java EE Support Patterns

1.22.2012

java.lang.NullPointerException: How to resolve

Exception in thread "main" java.lang.NullPointerException is one of the common problems and Java error that you will face when developing Java or Java EE applications. This Java Exception has been around since early JDK days e.g. JDK 1.0.

Most of you probably have seen and resolve this problem multiple times so this article is mainly dedicated for individuals new in Java or interested to revisit this Java Exception.

java.lang.NullPointerException: Overview

NullPointerException is a runtime Exception thrown by the JVM when your application code, other referenced API(s) or middleware (Weblogic, WAS, JBoss...) encounters the following conditions:

-        Attempting to invoke an instance method of a null object
-        Attempting to access or modify a particular field of a null object
-        Attempting to obtain the length of such null object as an array

java.lang.NullPointerException: Sample Java program

** A YouTube tutorial video is now available.

It is always best to learn with examples and sample Java programs. The program below is a very simple Java program generating a java.lang.NullPointerException. Please simply copy/paste and run the program with the IDE of your choice (Eclipse IDE was used for this example).

package org.ph.java.courses;

/**
 * NullPointerExceptionSampleProgram
 * @author Pierre-Hugues Charbonneau
 *
 */
public class NullPointerExceptionSampleProgram {
      
       private String field1 = null;
       private String field2 = null;   
      
       public String getField1() {
             return field1;
       }

       public void setField1(String field1) {
             this.field1 = field1;
       }

       public String getField2() {
             return field2;
       }

       public void setField2(String field2) {
             this.field2 = field2;
       }

       /**
        * @param args
        */
       public static void main(String[] args) {
            
             try {
                    // Create a fresh object instance
                    NullPointerExceptionSampleProgram objectInstance =
                                 new NullPointerExceptionSampleProgram();                   
                    // Initialize field1...
                    objectInstance.setField1("field1Value");
                   
                    // reset our object instance to null
                    objectInstance = null;
                   
                    // Now initialize field2...BOOM! >> NullPointerException!
                    objectInstance.setField2("field1Value2");
            
             } catch (Throwable any) {
                    System.out.println("Java ERROR: "+any);
                    any.printStackTrace();
             }
            
       }

}

If you run the program as is, you will see the output as per below:

java.lang.NullPointerException
       at org.ph.java.courses.NullPointerExceptionSampleProgram.main
(NullPointerExceptionSampleProgram.java:47)

Java ERROR: java.lang.NullPointerException

As you can see in our example, the NullPointerException is thrown when attempting to execute the setField2() method against our objectInstance which is now null.

The JVM will typically show you the line of code (line 47 in this example) where the NullPointerException is triggered. This is critical data since it allows you to trace back the problem in your application Java code at this particular line of code of the affected Java class.

java.lang.NullPointerException: Resolution strategies

Now that you understand this problem, it is now time to resolve it. Complexity of the resolution will depend of the context of your problem since NullPointerException can be a problem by itself or simply a symptom of another problem (no data returned from a Web Service call etc.). Regardless of the context & root cause, you must shield your Java code and add proper error handling and null check validations when applicable:

-        Review the java.lang.NullPointerException Stack Trace and determine where the Exception is triggered (your application code, third part API, middleware software such as Weblogic etc.) and extract the line #
-        If problem is at your application code then a code walkthrough will be required. If problem is found from third party API and / or middleware, my recommendation is to first review your referenced code and determine if it could be indirectly be the source of the problem e.g. passing a null value to a third part API method etc.
-        If problem found within your application code, then attempt to determine which Object instance is null and causing the problem. You will need to modify your code in order to add proper null check validations and proper logging so you can understand the source of the null value as well

Now back at our example, a simple validation and logging can be added as per below:

** Please note that logging should be done via standard logging framework such as Log4J **

// Now Initialize field2 but only if objectInstance is not null
if (objectInstance != null) {
objectInstance.setField2("field1Value2");
} else{
       System.out.println("objectInstance is null, do not attempt to initialize field2");
}

Conclusion and best practices

Best practices include:

-        Add proper null check validations before attempting to use an object Instance method e.g. if (objectInstance != null) { objectInstance.method(); }
-        When a null object is found, please add proper logging so you can pinpoint the root cause / source of the null value
-        Avoid too many object instance method calls on a single line as it will increase diagnostic complexity in the event of a NullPointerException e.g. avoid calls like this below unless properly checked for null prior to the call:
objectInstance.method(objectInstance2.getData(), objectInstance3.getData(),objectInstance4.getData());

I hope this article has helped you to understand and revisit this Java Exception.
Please feel free to add any comment or question if you are still struggling with a java.lang.NullPointerException problem.

1.20.2012

GC overhead limit exceeded: Understand your JVM

For JVM related problems and tuning, I always recommend application support individuals to improve their basic JVM skills. The OpenJDK HotSpot implementation (c++ code) allows you to understand at a lower level the JVM business logic and memory conditions triggering errors such as GC overhead limit exceeded.

This article will attempt to dissect the JVM business logic so you can better understand this severe Java memory condition.

java.lang.OutOfMemoryError: GC overhead limit exceeded

Before going any deeper into this problem and HotSpot implementation, I first recommend that you review my first 2 articles on the subjects as they will provide you an overview of this problem along with common patterns and recommendations:


HotSpot implementation – GC overhead limit exceeded logic

Find below a JVM c++ code snippet showing you both the pseudo code and implementation of the JVM logic leading to the GC overhead limit exceeded error message.

The primary criteria’s and conditions leading to GC overhead limit exceeded are as per below:

1)     Full GC triggered / observed
2)     GC cost e.g. everage time is higher than default limit. This means the time spent in GC is way too high
3)     The amount of memory available is smaller than limit e.g. this means your JVM is very close to full depletion (OldGen + YoungGen)
4)     The GC overhead limit count is reached e.g. typically 5 iterations limit is the default

Now please find below a snippet of the OpenJDK HotSpot implementation (c++). You can download the full OpenSource HotSpot implementation at:

  bool print_gc_overhead_limit_would_be_exceeded = false;
  if (is_full_gc) {
    if (gc_cost() > gc_cost_limit &&
      free_in_old_gen < (size_t) mem_free_old_limit &&
      free_in_eden < (size_t) mem_free_eden_limit) {
      // Collections, on average, are taking too much time, and
      //      gc_cost() > gc_cost_limit
      // we have too little space available after a full gc.
      //      total_free_limit < mem_free_limit
      // where
      //   total_free_limit is the free space available in
      //     both generations
      //   total_mem is the total space available for allocation
      //     in both generations (survivor spaces are not included
      //     just as they are not included in eden_limit).
      //   mem_free_limit is a fraction of total_mem judged to be an
      //     acceptable amount that is still unused.
      // The heap can ask for the value of this variable when deciding
      // whether to thrown an OutOfMemory error.
      // Note that the gc time limit test only works for the collections
      // of the young gen + tenured gen and not for collections of the
      // permanent gen.  That is because the calculation of the space
      // freed by the collection is the free space in the young gen +
      // tenured gen.
      // At this point the GC overhead limit is being exceeded.
      inc_gc_overhead_limit_count();
      if (UseGCOverheadLimit) {
        if (gc_overhead_limit_count() >=
            AdaptiveSizePolicyGCTimeLimitThreshold){
          // All conditions have been met for throwing an out-of-memory
          set_gc_overhead_limit_exceeded(true);
          // Avoid consecutive OOM due to the gc time limit by resetting
          // the counter.
          reset_gc_overhead_limit_count();
        } else {
          // The required consecutive collections which exceed the
          // GC time limit may or may not have been reached. We
          // are approaching that condition and so as not to
          // throw an out-of-memory before all SoftRef's have been
          // cleared, set _should_clear_all_soft_refs in CollectorPolicy.
          // The clearing will be done on the next GC.
          bool near_limit = gc_overhead_limit_near();
          if (near_limit) {
            collector_policy->set_should_clear_all_soft_refs(true);
            if (PrintGCDetails && Verbose) {
              gclog_or_tty->print_cr("  Nearing GC overhead limit, "
                "will be clearing all SoftReference");
            }
          }
        }
      }
      // Set this even when the overhead limit will not
      // cause an out-of-memory.  Diagnostic message indicating
      // that the overhead limit is being exceeded is sometimes
      // printed.
      print_gc_overhead_limit_would_be_exceeded = true;

    } else {
      // Did not exceed overhead limits
      reset_gc_overhead_limit_count();
    }
  }


Please feel free to post any comment or ask me any question.

1.12.2012

How to analyze Thread Dump – Part2: JVM Overview

Before going deeper into Thread Dump analysis and problem patterns, it is very important that you understand the fundamentals. The post will cover the basics and allow you to better your JVM and middleware interaction with your Java EE container.

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

Java VM overview

The Java virtual machine is really the foundation of any Java EE platform. This is where your middleware and applications are deployed and active.

The JVM provides the middleware software and your Java / Java EE program with:

-        A runtime environment for your Java / Java EE program (bytecode format)

-        Several program features and utilities (IO facilities, data structure, Threads management, security, monitoring etc.)
-        Dynamic memory allocation and management via the garbage collector

Your JVM can reside on many OS (Solaris, AIX, Windows etc.) and depending of your physical server specifications, you can install 1...n JVM processes per physical / virtual server.

JVM and Middleware software interactions

Find below a diagram showing you a high level interaction view between the JVM, middleware and application(s).


This is showing you a typical and simple interaction diagram between the JVM, middleware and application. As you can see, the Threads allocation for a standard Java EE application are done mainly between the middleware kernel itself and JVM (there are some exceptions when application itself or some APIs create Threads directly but this is not common and must be done very carefully).

Also, please note that certain Threads are managed internally within the JVM itself such as GC (garbage collection) Threads in order to handle concurrent garbage collections.

Since most of the Thread allocations are done by the Java EE container, it is important that you understand and recognize the Thread Stack Trace and identify it properly from the Thread Dump data. This will allow you to understand quickly the type of request that the Java EE container is attempting to execute.

From a Thread Dump analysis perspective, you will learn how to differentiate between the different Thread Pools found from the JVM and identify the request type.

The Thread Dump Analysis Part 3 is now available and will provide you a high level overview of a Thread Dump and breakdown for the HotSpot VM 1.6 Thread Dump format.

1.10.2012

Java stop Thread? Think again

When facing a stuck Thread problem, a common question is how can I dynamically kill the observed stuck Threads in order to quickly recover my middleware environment?

This is a question I’m getting quite often from my work colleagues and clients.

This short article will provide you with background on why this is not a good idea and not possible with current Java specifications and high level strategies to prevent stuck Threads at the first place.

Stuck Thread – What is it?

Stuck Thread problems are very common and can be hard to solve. A stuck Thread is basically a Thread which is hanging and / or has stopped its current assigned tasks for various reasons:

·         Thread waiting on a blocking IO call ex: hanging socket.read() operation
·         Thread waiting to acquire a lock on an Object monitor (synchronized)
·         Thread forced to go in the wait() state ex: waiting to acquire a free JDBC Connection from a pool etc.
·         Thread involved in a real deadlock scenario e.g. Thread A waiting on Object monitor held by Thread B, Thread B waiting on Object monitor held by Thread A
·         Thread hanging on a disk IO operation
·         Thread hanging / paused due to excessive garbage collection going on
·         More scenarios…


Exactly the problem I’m facing, please tell me how I can kill these stuck Threads

The simple answer is that you cannot. Earlier Java specifications used to have Thread.stop().
This method was originally designed to destroy a thread without any cleanup:

·         Any monitors it held would have remained locked. However, the method was never implemented. If it were to be implemented, it would be deadlock-prone in much the manner of suspend().
·          If the target thread held a lock protecting a critical system resource when it was destroyed, no thread could ever access this resource again.
·         If another thread ever attempted to lock this resource, deadlock would result. Such deadlocks typically manifest themselves as "frozen" processes.

You can also consult the official Oracle documentation on this subject.

As you can see, because of the above risk scenarios, such Thread stop mechanism is not implemented which does not allow your middleware vendor to expose any Thread stop button / functionality to the end user / middleware administrator.

In order to terminate stuck Threads, you have to bring down the entire JVM.

Any proposed solution?

Your best strategy is to prevent stuck Threads at the first place as much as possible and to properly perform root cause analysis & Thread Dump analysis post stuck Thread related incidents. As you can see in the above scenarios, typical stuck Thread problems are just “symptoms” of other problems so solutions include:

·         Proper timeout implementation to prevent forever hanging stuck Thread on blocking IO calls. Most communication API out there properly expose timeout methods allowing you to cap in seconds how long you are allowing your Threads to wait on remote resources (Web Services etc.)
·         Application code should be reviewed and optimized in order to eliminate wrong synchronized usage
·         Proper capacity planning of your environment is a must in order to prevent overload of key infrastructure components such as an Oracle DB which can trigger slow running queries and stuck Thread on middleware side
·          Deadlock scenarios are usually symptoms of code problem / code not Thread safe ex: re-using the same JDBC Connection object between 2..n Threads
·         Excessive IO / disk access can trigger stuck Threads, again symptoms of application problem(s) performing too much IO / class loading calls etc.
·         Lack of tuning, capacity planning and / or Java Heap memory leak may lead to excessive garbage collection and inevitably to stuck Threads; again symptoms of a bigger problem which requires proper Java Heap tuning and Heap Dump / application memory footprint analysis
 
I hope this article has helped you understand why you cannot and should not rely on Thread.stop() to fix your stuck Thread problems and strategies to prevent these problems at the first place.

Please don’t hesitate to post any comment or question about any stuck Thread problem you are currently facing.