Saturday, August 31, 2013

NetBeans 7.4 Beta Hints Warn of Ineffective Exception Handling

There are numerous examples of how Java exception handling can be more difficult than it might first appear and Josh Bloch devoted an entire chapter of Effective Java (both editions) to exception handling. The checked exception model in Java remains "controversial." I was pleased to see that the NetBeans 7.4 beta I recently downloaded has some hints to help with at least a few nuances of Java exception handling.

I recently downloaded NetBeans 7.4 beta and installed this latest version of NetBeans on my laptop. I downloaded the "All" NetBeans IDE Download Bundle (includes GlassFish Server Open Source Edition 4.0 and Apache Tomcat 7.0.41 and Groovy support) and installed it on my machine.

Two of the new hints in the "probable bugs" category that are in the "current development version" of NetBeans are "'finally' block suppresses exceptions" and "'throw' inside 'finally' block." In this blog post, I will demonstrate these hints and briefly discuss why the hints help improve exception handling.

'finally' block suppresses exceptions

As documented in posts such as James Stauffer's Don't return in a finally clause and in forums such as Java try-finally return design question, it is generally accepted that having a method return from a finally block is a bad idea. An example of this poor Java coding practice is shown next.

Example of finally Block Suppressing Exception
private void throwException() throws Exception
{
   throw new Exception("A checked exception!");
}

/**
 * Demonstrate NetBeans hint "The 'return' statement in the 'finally' block
 * discards unhandled exceptions" by returning a value from the "finally"
 * block.
 * 
 * @return Integer value that is really meaningless in this case.
 * @throws RuntimeException This exception is always thrown.
 */
public int demonstrateReturnFromFinallyBlock()
{
   int value = 5;
   try
   {
      value = 7;
      throwException();
   }
   catch (Exception exception)
   {
      throw new RuntimeException(exception);
   }
   finally
   {
      return value;
   }
}

When the method demonstrateReturnFromFinallyBlock() in the above code snippet is executed, the output appears as follows:

Returned Value: 7

Although one might expect the demonstrateReturnFromFinallyBlock() method to throw a Runtime exception instead of returning an integer value of 7 (as the Javadoc for that method even advertises!), the "always thrown" exception is actually discarded because of the return statement in the finally block. This is a potentially nasty issue that might only be obvious at runtime rather than at compile time. Fortunately, NetBeans 7.4 beta includes a hint about this potential issue as demonstrated in the next screen snapshot:

The above screen snapshot demonstrates NetBeans 7.4 beta warns of the condition of a return statement in a finally block by underlining it in yellow. It also shows that when one hovers over that yellow-underlined piece of code, the NetBeans editor hints "The 'return' statement in the 'finally' block discards unhandled exceptions."

One can also find out about this same condition by passing -Xlint:finally to the javac compiler. This can obviously be done on the command line as I previously blogged about in javac's -Xlint Options, but the next screen snapshot shows the same thing being done in NetBeans through specification of -Xlint:finally via project.properties setting javac.compilerargs=-Xlint:finally.

'throw' inside 'finally' block

Throwing an exception from inside of a finally block is generally a bad idea because it will hide any exception thrown in that finally block's associated try block. The next code listing shows an example of this bad form.

/**
 * Demonstrate NetBeans hint warning that throwing an exception from a
 * 'finally' block is a bad idea because it hides the original exception.
 */
public void demonstrateThrowFromFinallyBlock()
{
   Integer twoDividedByZero = null;
   try
   {
      twoDividedByZero = 2 / 0;
   }
   finally
   {
      if (twoDividedByZero == null)
      {
         throw new RuntimeException("Cannot calculate quotient with division.");
      }
   }
}

One might think that executing the above method would result in an ArithmeticException being thrown and might be a bit surprised when a more general (and parent) RuntimeException is thrown instead.

The next screen snapshot shows NetBeans 7.4 beta warning of this condition.

Hovering over the yellow underlined code leads to display of the NetBeans warning "The 'throw' statement in 'finally' block may hide the original exception." The above screen snapshot shows this to be exactly what happened in this case: the ArithmeticException and its stack trace were hidden by the RuntimeException thrown from the finally block.

If I comment out the line throwing the exception from the finally block, the original exception is available again. This is demonstrated in the next screen snapshot.

Enabling even -Xlint:all (or simply -Xlint) will not warn of the bad form of throwing an exception from a finally block. In this particular example, the -Xlint:devzero (or -Xlint:all or -Xlint) would have shown that a divide by zero occurs in the code, but in general there is no -Xlint warning to have javac warn you when throwing from a finally block is hiding an original exception. This makes this particular NetBeans hint particularly useful.

Conclusion

There are many nuances and corner cases in Java exception handling. NetBeans 7.4 beta introduces two new "probable bugs" hints that warn of dangerous practices in exception-related finally blocks. The two cases are particularly insidious because they are not generally caught by the compiler (although one can optionally be caught as a warning), will not be found until runtime, and are not likely to be discovered easily from reading and reviewing the code.

No comments: