Wiki Markup |
---|
Programs must not catch {{java.lang.NullPointerException}}. A {{NullPointerException}} exception thrown at runtime indicates the existence of an underlying {{null}} pointer dereference that must be fixed in the application code (see rule [EXP01-J. Never dereference null pointers] 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, _avoiding_ the exception by catching {{NullPointerException}} adds significantly more performance overhead than simply adding the necessary checks \[[Bloch 2008|AA. Bibliography#Bloch 08]\]. Second, when there are multiple expressions in a {{try}} block that are capable of throwing a {{NullPointerException}}, it is difficult or impossible to determine which expression is responsible for the exception because the {{NullPointerException}} {{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 RuntimeException
or or its ancestors, Exception
or 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 NullPointerException
and ArrayIndexOutOfBoundsException
. Many catch
clauses simply log or ignore the enclosed exceptional condition and attempt to resume normal execution; this practice often violates rule 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.
...
Compliant Solution
This compliant solution performs no null check 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 function method that throws a NullPointerException
without a null check must provide a precondition that the argument being passed to it is not null.
...
Wiki Markup |
---|
This noncompliant code example is derived from the logging service null object design pattern described by Henney \[[Henney 2003|AA. Bibliography#Henney 03]\]. 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}} class. |
...
This design choice suppresses genuine occurrences of NullPointerException
. It also violates the design principle that exceptions should be used only for exceptional conditions; ignoring a null Log
object is part of the ordinary operation for 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.
...
An acceptable alternative implementation uses a setter method and a getter method to control all interaction with the reference to the current log. The setter ensures use of the null object in place of a null reference. The getter ensures that any retrieved instance is either an actual logger or a null object (but never a null reference). Instances of the Null Object null object are immutable and are inherently thread-safe. Classes that provide setter or getter methods must comply with the second exception of OBJ05-J. Defensively copy private mutable class members before returning their references.
Wiki Markup |
---|
Some |
Wiki Markup |
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|AA. Bibliography#Cunningham 95]\]. This can be a useful alternative to returning {{null}}. |
...
In this noncompliant code example, the original version of the division()
method was is declared to throw only ArithmeticException
. However, the caller catches a the more general Exception
type (Exception
) to report arithmetic problems rather than catching the specific exception ArithmeticException
type (ArithmeticException
). This practice is insecure because future changes to the method signature could add to the list of potential exceptions the caller must handle. In this example, a newer version of the division()
method can potentially throw IOException
in addition to ArithmeticException
. However, the compiler cannot tell inform the caller's developer that he must to provide a corresponding handler because his or her existing code already catches IOException
as a result of catching Exception
. Consequently, the recovery process may 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.
Code Block | ||
---|---|---|
| ||
public class DivideException { public static void main(String[] args) { try { division(200, 5); division(200, 0); // Divide by zero } catch (Exception e) { System.out.println("Divide by zero exception : " + e.getMessage()); + e.getMessage()); } } public static void division(int totalSum, int totalNumber) throws ArithmeticException, IOException { int average = totalSum / totalNumber; // Additional operations that may throw IOException... System.out.println("Average: " + average); } } |
...
This noncompliant code example attempts improvement by specifically catching ArithmeticException
. However, it continues to catch Exception
and consequently catches both unanticipated checked exceptions and also unanticipated runtime exceptions.
...
Code Block | ||
---|---|---|
| ||
import java.io.IOException; public class DivideException { public static void main(String[] args) { try { division(200, 5); division(200, 0); // Divide by zero } catch (ArithmeticException ae) { throw new DivideByZeroException(); // DivideByZeroException extends Exception so is checked throw new DivideByZeroException(); } catch (IOException ex) { ExceptionReporter.report(ex); } } public static void division(int totalSum, int totalNumber) throws ArithmeticException, IOException { int average = totalSum / totalNumber; // Additional operations that may throw IOException... System.out.println("Average: "+ average); } } |
...
The ExceptionReporter
class is documented in rule ERR00-J. Do not suppress or ignore checked exceptions.
Compliant Solution (Java 1.7)
Java 1.7 allows a single catch
block to catch multiple exceptions . This allows one catch block to handle exceptions of different types, which prevents redundant code. This compliant solution catches the specific anticipated exceptions (ArithmeticException
and IOException
) and handles them with one catch clause. All other exceptions are permitted to propagate to the next nearest dynamically enclosing catch
clause of a try
statement statement on the stack.
Code Block | ||
---|---|---|
| ||
import java.io.IOException;
public class DivideException {
public static void main(String[] args) {
try {
division(200, 5);
division(200, 0); // Divide by zero
} catch (ArithmeticException|IOException ex) {
ExceptionReporter.report(ex);
}
}
public static void division(int totalSum, int totalNumber)
throws ArithmeticException, IOException {
int average = totalSum / totalNumber;
// Additional operations that may throw IOException...
System.out.println("Average: "+ average);
}
}
|
...
Exceptions
EXC08ERR08-EX0: A 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 to ruleERR01-J. Do not allow exceptions to expose sensitive information, as well as and weaknesses CWE 7 and CWE 388. In such cases, a catch
block should catch Throwable
rather than Exception
or RuntimeException
.
...
Exception wrapping is a common technique to safely handle unknown exceptions. For another example, see rule ERR06-J. Do not throw undeclared checked exceptions.
Wiki Markup |
---|
*EXC08ERR08-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 {{Runnable}} \[[Goetz 2006|AA. Bibliography#Goetz 06], pgp. 161\]. |
EXC08-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.
...