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 nonnull
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.
In the Nullable tab, click on the + button.
Type
ej.annotation.Nullable
and select the listed class.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.
Check and select the category Java > Probable Bugs > Nullability problems > Return of ‘null’.
Change the Severity field to Error.
Select the category Java > Probable Bugs > Nullability problems > Return value is outside of declared range.
Change the Severity field to Error.
Select the category Java > Probable Bugs > Nullability and data flow problems.
Change the Severity field to Error.
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.
Check and select the category Java > Javadoc > Missing’package-info.java’.
Change the Severity field to Error.
For more details, refer to the official documentation on Configure nullability annotations.
To enable the Null Analysis tool in Eclipse, a project must be configured as follows:
In the Package Explorer, right-click on the module project and select Properties,
Navigate to Java Compiler > Errors/Warnings,
In the Null analysis section, configure options as follows:
Click on the Configure… link to configure MicroEJ annotations:
ej.annotation.Nullable
ej.annotation.NonNull
ej.annotation.NonNullByDefault
In the Annotations section, check Suppress optional errors with ‘@SuppressWarnings’ option:
This option allows to fully ignore Null Analysis errors in advanced cases using
@SuppressWarnings("null")
annotation.
If you have multiple projects to configure, you can then copy the content of the .settings
folder to an other module project.
Warning
You may lose information if your target module project already has custom parameterization or if it was created with another SDK version. In case of any doubt, please configure the options manually or merge with a text file comparator.
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:
The Null Analysis can be automatically disabled in test folder by using the eclipse-wtp
Gradle plugin:
In the
build.gradle.kts
plugin of the project, add theeclipse-wtp
plugin:plugins { ... `eclipse-wtp` }
Then add the following snippet of code:
import org.gradle.plugins.ide.eclipse.model.AbstractClasspathEntry import org.gradle.plugins.ide.eclipse.model.Classpath eclipse.classpath.file { whenMerged(Action<Classpath> { entries.filter { entry -> (entry.kind == "src" && entry is AbstractClasspathEntry && entry.path == "src/test/java") }.forEach { entry -> (entry as AbstractClasspathEntry).entryAttributes["ignore_optional_problems"] = "true" } }) }
Adapth the path of your test folder accordingly.
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 nonnull
.Collections of the Java Collections Framework that can hold
null
elements (e.g. HashMap) do not acceptnull
elements. This allows APIs to returnnull
(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.