NonNull type annotation and checker

This document describes the @NonNull type annotation, and a checker (a compiler plugin) for it.

If the checker issues no warnings for a given program, then running that program will never throw a null pointer exception. This guarantee enables a programmer to prevent errors from occurring when his program is run.

The non-null checking plugin is distributed as part of the JSR 308 checkers framework.

Contents:

Annotating your code with @NonNull

In order to perform checking, you must annotate your code with the @NonNull type annotation, which indicates a type that does not include the null value. (You should also add import checkers.quals.*; at the top of your source file, to permit use of @NonNull.)

A variable of type Boolean always has one of the values TRUE, FALSE, or null. By contrast, a variable of type @NonNull Boolean always has one of the values TRUE, or FALSE — never null. Dereferencing an expression of type @NonNull Boolean can never cause a null pointer exception.

The plugin issues a warning in two cases:

  1. When an expression of non-@NonNull type is dereferenced, because it might cause a null pointer exception
  2. When an expression of @NonNull might become null, because it is a misuse of the type

This example shows both sorts of problems:

           Object   obj;  // might be null
  @NonNull Object nnobj;  // never null
  ...
  nnobj.toString()  // checker warning:  dereference might cause null pointer exception
  nnobj = obj;      // checker warning:  nnobj may become null

Parameter passing and return values are checked analogously to assignments.

Implicit non-null types (flow-sensitive inference)

In order to reduce the burden of annotating types in your program with @NonNull (or adding casts and new declarations to your program), the plugin infers non-null types for some variables and expressions, and treats them that way even when you have not annotated them. These implicitly non-null types permit deferences, and assignments to explicitly non-null types, without compiler warnings.

For example, consider this code. Note that the same expression may yield a warning or not depending on its context.

  // Requires an argument of type @NonNull String
  void parse(@NonNull String toParse) { ... }

  void lex(String toLex) {
    String s;    // s does NOT have a @NonNull type
    ...
    parse(s);        // warning:  s might be null
    ...
    if (s != null) {
      parse(s);      // no warning:  s is known to be non-null
    }
    ...
    parse(s);        // warning:  s might be null
    ...
    s = new String(...);
    parse(s);        // no warning:  s is known to be non-null
  }

Flow-sensitive non-null inference has been implemented for the following varieties of expressions:

Note: The items in the above list exclude complex null checks, i.e., not of the form x != null. Support for these types of checks will be available in a future release.

Non-null inference is never performed for method parameters of non-private methods and for non-private fields, because unknown client code could use them in arbitrary ways. The inferred information is never written to the .class file as user-written annotations are.

The inference indicates when an un-annotated type can be treated as a @NonNull one. An expression of @NonNull type is never inferred to be treated as non-null; any such use is an error, and the checker issues a warning.

Example use

Tiny examples

To try the @NonNull plugin on a source file that uses the @NonNull qualifier, use the following command (where javac is the JSR 308 compiler):

  javac -typeprocessor checkers.nonnull.NonnullChecker examples/NonNullExample.java

Compilation will complete without warnings.

To see the checker warn about incorrect usage of annotations (and therefore the possibility of a null pointer exception at run time), use the following command:

  javac -typeprocessor checkers.nonnull.NonnullChecker examples/NonNullExampleWithWarnings.java

The compiler will issue three warnings regarding violation of the semantics of @NonNull in the NonNullExampleWithWarnings.java file.

Annotated library

In addition to the tiny examples distributed with the checker, you can also run the nonnull checker on the annotation scene library, a larger library that has been fully annotated with @NonNull. To run the nonnull checker on the annotation scene library, first download the scene library suite (which includes build dependencies for the scene library as well as its source code) and extract it into your checkers installation. The checker can then be run on the annotation scene library with Apache Ant using the following commands:

  cd $CHECKERS
  ant -f scene-lib-test.xml

where $CHECKERS is the location of the checkers installation.

You can view the annotated source code, which contains @NonNull annotations, in the checkers/scene-lib-test/src/annotations/ directory.

Caveats to the guarantee of no null pointer errors

The plugin prevents null pointer errors in your code. In addition to the caveats for any checker, there are two additional caveats:

Credits and related work

If you have any problem with the @NonNull checker, please see “How to report bugs” for information on reporting bugs, so that we can improve it in a future release.

The @NonNull annotation described in this document is similar, but not identical, to the @NotNull annotation of IntelliJ IDEA, the @NonNull annotation of FindBugs, the non_null modifier of JML, and annotations proposed by JSR 305, among others.


Back to the JSR 308 checkers framework.