Null Analysis

NullPointerException thrown at runtime is one of the most common causes for failure of Java programs. All modern IDEs provide a Null Analysis tool which can detect such programming errors (misuse of potential null Java values) at compile-time.

Principle

The Null Analysis tool is based on Java annotations. Each Java field, method parameter and method return value must be marked to indicate whether it can be null or not.

Once the Java code is annotated, the IDE must be configured to enable Null Analysis detection.

Java Code Annotation

MicroEJ defines its own annotations:

  • @NonNullByDefault: Indicates that all fields, method return values or parameters can never be null in the annotated package or type. This rule can be overridden on each element by using the @Nullable annotation.

  • @Nullable: Indicates that a field, local variable, method return value or parameter can be null.

  • @NonNull: Indicates that a field, local variable, method return value or parameter can never be null.

MicroEJ recommends to annotate the Java code as follows:

  • In each Java package, create a package-info.java file and annotate the Java package with @NonNullByDefault. This is a common good practice to deal with non null elements by default to avoid undesired NullPointerException. It enforces the behavior which is already widely outlined in Java coding rules.

    @ej.annotation.NonNullByDefault
    package com.mycompany;
    
  • In each Java type, annotate all fields, methods return values and parameters that can be null with @Nullable. Usually, this information is already available as textual information in the field or method Javadoc comment. The following example of code shows where annotations must be placed:

    @Nullable
    public Object thisFieldCanBeNull;
    
    @Nullable
    public Object thisMethodCanReturnNull() {
      return null;
    }
    
    public void thisMethodParameterCanBeNull(@Nullable Object param) {
    
    }
    

IDE Configuration

Requirements

The project must depend at least on the version 1.3.6 of the ej.api:edc module:

dependencies {
  implementation("ej.api:edc:1.3.6")
}

Project configuration

Follow these steps to enable the Null Analysis tool in Android Studio and IntelliJ IDEA:

  • Go to File > Settings….

  • Go to Editor > Inspections.

  • Open the category Java > Probable Bugs > Nullability problems > @NotNull/@Nullable problems.

  • In the Options panel, scroll down and click on the Configure Annotations… button.

    Null Analysis Checks Configuration in IntelliJ IDEA and Android
  • In the Nullable tab, click on the + button.

  • Type ej.annotation.Nullable and select the listed class.

    Nullable Annotation Configuration in IntelliJ IDEA and Android
  • Select ej.annotation.Nullable in the Nullable annotations list.

  • Go to the NotNull tab and repeat the same steps with the ej.annotation.NonNull class.

  • Click on the OK button.

  • Change the Severity field to Error.

  • Check the Report @NotNull parameters overriding non-annotated option.

    Nullable Annotation Configuration in IntelliJ IDEA and Android
  • Check and select the category Java > Probable Bugs > Nullability problems > Return of ‘null’.

  • Change the Severity field to Error.

    Nullable Annotation Configuration in IntelliJ IDEA and Android
  • Select the category Java > Probable Bugs > Nullability problems > Return value is outside of declared range.

  • Change the Severity field to Error.

    Nullable Annotation Configuration in IntelliJ IDEA and Android
  • Select the category Java > Probable Bugs > Nullability and data flow problems.

  • Change the Severity field to Error.

    Nullable Annotation Configuration in IntelliJ IDEA and Android
  • Check and select the category Java > Probable Bugs > Nullability problems > @NotNull field is not initialized.

  • Change the Severity field to Error.

  • Uncheck the Ignore fields which could be initialized implicitly option.

  • Uncheck the Ignore fields initialized in setUp() method option.

    Nullable Annotation Configuration in IntelliJ IDEA and Android
  • Check and select the category Java > Javadoc > Missing’package-info.java’.

  • Change the Severity field to Error.

    Nullable Annotation Configuration in IntelliJ IDEA and Android

For more details, refer to the official documentation on Configure nullability annotations.

Launching Null Analysis

While Eclipse automatically launches Null Analysis on the whole project and reports all the problems found, IntelliJ IDEA and Android Studio launch the Null Analysis only on the currently open file. In order to launch an Analysis of the full project:

  • Go to Code > Inspect Code.

  • Check the Whole project option.

  • Uncheck the Include test sources option.

  • Click on Analyze.

Disabling Analysis for Test Folder

The Analysis of the test folder can be disabled by unchecking the option Include test sources when launching a Code Inspection:

Disabling Analysis in Test Folder

Sharing Null Analysis IDE Configuration

The configuration related to Null Analysis is located in the .idea/misc.xml and .idea/inspectionProfiles/* files. In order to share them, they must be committed in your project source reposiory. For Git projects, if you decided to not commit the IDE configuration files, these files can be excluded with the following lines in the .gitignore file:

/.idea/*
!/.idea/misc.xml
!/.idea/inspectionProfiles/*

.. warning::

  Android Studio and IntelliJ IDEA create a ``.gitignore`` file in the ``.idea`` folder.
  You can remove it or adapt it to fit your needs.

MicroEJ Libraries

Many libraries available on Central Repository are annotated with Null Analysis. If you are using a library which is not yet annotated, please contact our support team.

For the benefit of Null Analysis, some APIs have been slightly constrained compared to the Javadoc description. Here are some examples to illustrate the philosophy:

  • System.getProperty(String key, String def) does not accept a null default value, which allows to ensure the returned value is always non null.

  • Collections of the Java Collections Framework that can hold null elements (e.g. HashMap) do not accept null elements. This allows APIs to return null (e.g. HashMap.get(Object)) only when an element is not contained in the collection.

Implementations are left unchanged and still comply with the Javadoc description whether the Null Analysis is enabled or not. So if these additional constraints are not acceptable for your project, please disable Null Analysis.