Programs must not catch
NullPointerException exception thrown at runtime indicates the existence of an underlying
null pointer dereference that must be fixed in the application code (see EXP01-J. Do not use a null in a case where an object is required for more information). Handling the underlying null pointer dereference by catching the
NullPointerException rather than fixing the underlying problem is inappropriate for several reasons. First, catching
NullPointerException adds significantly more performance overhead than simply adding the necessary null checks [Bloch 2008]. Second, when multiple expressions in a
try block are capable of throwing a
NullPointerException, it is difficult or impossible to determine which expression is responsible for the exception because the
catch block handles any
NullPointerException thrown from any location in the
try block. Third, programs rarely remain in an expected and usable state after a
NullPointerException has been thrown. Attempts to continue execution after first catching and logging (or worse, suppressing) the exception rarely succeed.
Likewise, programs must not catch
Throwable. Few, if any, methods are capable of handling all possible runtime exceptions. When a method catches
RuntimeException, it may receive exceptions unanticipated by the designer, including
catch clauses simply log or ignore the enclosed exceptional condition and attempt to resume normal execution; this practice often violates ERR00-J. Do not suppress or ignore checked exceptions. Runtime exceptions often indicate bugs in the program that should be fixed by the developer and often cause control flow vulnerabilities.
Noncompliant Code Example (
This noncompliant code example defines an
isName() method that takes a
String argument and returns true if the given string is a valid name. A valid name is defined as two capitalized words separated by one or more spaces. Rather than checking to see whether the given string is null, the method catches
NullPointerException and returns false.
This compliant solution explicitly checks the
String argument for
null rather than catching
This compliant solution omits an explicit check for a null reference and permits a
NullPointerException to be thrown:
Omitting the null check means that the program fails more quickly than if the program had returned false and lets an invoking method discover the null value. A method that throws a
NullPointerException without a null check must provide a precondition that the argument being passed to it is not null.
Noncompliant Code Example (Null Object Pattern)
This noncompliant code example is derived from the logging service Null Object design pattern described by Henney [Henney 2003]. The logging service is composed of two classes: one that prints the triggering activity's details to a disk file using the
FileLog class and another that prints to the console using the
ConsoleLog class. An interface,
Log, defines a
write() method that is implemented by the respective log classes. Method selection occurs polymorphically at runtime. The logging infrastructure is subsequently used by a
Service object must support the possibility that a
Log object may be
null because clients may choose not to perform logging. This noncompliant code example eliminates null checks by using a
try-catch block that ignores
This design choice suppresses genuine occurrences of
NullPointerException in violation of ERR00-J. Do not suppress or ignore checked exceptions. It also violates the design principle that exceptions should be used only for exceptional conditions because ignoring a null
Log object is part of the ordinary operation of a server.
Compliant Solution (Null Object Pattern)
The Null Object design pattern provides an alternative to the use of explicit null checks in code. It reduces the need for explicit null checks through the use of an explicit, safe null object rather than a null reference.
This compliant solution modifies the no-argument constructor of class
Service to use the do-nothing behavior provided by an additional class,
Log.NULL; it leaves the other classes unchanged.
log reference final ensures that its value is assigned during initialization.
An acceptable alternative implementation uses accessor methods to control all interaction with the reference to the current log. The accessor method to set a log ensures use of the null object in place of a null reference. The accessor method to get a log ensures that any retrieved instance is either an actual logger or a null object (but never a null reference). Instances of the null object are immutable and are inherently thread-safe.
Some system designs require returning a value from a method rather than implementing do-nothing behavior. One acceptable approach is use of an exceptional value object that throws an exception before the method returns [Cunningham 1995]. This approach can be a useful alternative to returning
In distributed environments, the null object must be passed by copy to ensure that remote systems avoid the overhead of a remote call argument evaluation on every access to the null object. Null object code for distributed environments must also implement the
Code that uses this pattern must be clearly documented to ensure that security-critical messages are never discarded because the pattern has been misapplied.
Noncompliant Code Example (Division)
This noncompliant code example assumes that the original version of the
division() method was declared to throw only
ArithmeticException. However, the caller catches the more general
Exception type to report arithmetic problems rather than catching the specific exception
ArithmeticException type. This practice is risky because future changes to the method signature could add more exceptions to the list of potential exceptions the caller must handle. In this example, a revision of the
division() method can throw
IOException in addition to
ArithmeticException. However, the compiler will not diagnose the lack of a corresponding handler because the invoking method already catches
IOException as a result of catching
Exception. Consequently, the recovery process might be inappropriate for the specific exception type that is thrown. Furthermore, the developer has failed to anticipate that catching
Exception also catches unchecked exceptions.
Noncompliant Code Example
This noncompliant code example attempts to solve the problem by specifically catching
ArithmeticException. However, it continues to catch
Exception and consequently catches both unanticipated checked exceptions and unanticipated runtime exceptions.
DivideByZeroException is a custom exception type that extends
This compliant solution catches only the specific anticipated exceptions (
IOException). All other exceptions are permitted to propagate up the call stack.
ExceptionReporter class is documented in ERR00-J. Do not suppress or ignore checked exceptions.
Compliant Solution (Java SE 7)
Java SE 7 allows a single
catch block to catch multiple exceptions of different types, which prevents redundant code. This compliant solution catches the specific anticipated exceptions (
IOException) and handles them with one catch clause. All other exceptions are permitted to propagate to the next
catch clause of a
try statement on the stack.
catch block may catch all exceptions to process them before rethrowing them (filtering sensitive information from exceptions before the call stack leaves a trust boundary, for example). Refer to ERR01-J. Do not allow exceptions to expose sensitive information and weaknesses CWE 7 and CWE 388 for more information. In such cases, a
catch block should catch
Throwable rather than
This code sample catches all exceptions and wraps them in a custom
DoSomethingException before rethrowing them:
Exception wrapping is a common technique to safely handle unknown exceptions. For another example, see ERR06-J. Do not throw undeclared checked exceptions.
ERR08-J-EX1: Task processing threads such as worker threads in a thread pool or the Swing event dispatch thread are permitted to catch
RuntimeException when they call untrusted code through an abstraction such as the
Runnable interface [Goetz 2006, p. 161].
ERR08-J-EX2: Systems that require substantial fault tolerance or graceful degradation are permitted to catch and log general exceptions such as
Throwable at appropriate levels of abstraction. For example:
- A real-time control system that catches and logs all exceptions at the outermost layer, followed by warm-starting the system so that real-time control can continue. Such approaches are clearly justified when program termination would have safety-critical or mission-critical consequences.
- A system that catches all exceptions that propagate out of each major subsystem, logs the exceptions for later debugging, and subsequently shuts down the failing subsystem (perhaps replacing it with a much simpler, limited-functionality version) while continuing other services.
NullPointerException may mask an underlying null dereference, degrade application performance, and result in code that is hard to understand and maintain. Likewise, catching
Throwable may unintentionally trap other exception types and prevent them from being handled properly.
|PMD.Strict-Exceptions.AvoidCatchingThrowable||Avoid catching Throwable|