-
Notifications
You must be signed in to change notification settings - Fork 366
Adopting NullAway
The first build on an existing codebase reports every dereference, assignment, and field NullAway cannot prove safe, which on a large codebase is a long list. The steps below keep that list manageable, and cover the two migrations that usually come later. The README has the build setup each step assumes.
- Get Error Prone running on its own, and confirm the build is still green. NullAway is a plugin; a problem at this stage is an Error Prone problem. See the Error Prone installation docs, and Configuration for Maven, Bazel, and other build systems.
-
Tell NullAway which code is annotated. Exactly one of two options must be passed. For a codebase adopting JSpecify, pass
-XepOpt:NullAway:OnlyNullMarked=true, which requires NullAway 0.12.3 or later, and mark packages@NullMarkedas you go. Otherwise pass-XepOpt:NullAway:AnnotatedPackageswith your own package prefixes. Without one of them NullAway refuses to run. -
Leave the severity at warning. NullAway reports warnings by default;
-Xep:NullAway:ERRORpromotes them. Build once and read the count before promoting anything. -
Fix or annotate what the first build reports. Most reports are a missing
@Nullableon a field, parameter, or return. Error Messages explains each one. Where a value genuinely cannot be null but NullAway cannot prove it, Suppressing Warnings describescastToNonNull. - Suppress the remainder in bulk, if the count is large. See the next section.
- Promote to error so that new code cannot add reports, and work the suppressions down from there.
For a codebase too large to annotate in one sitting, NullAway emits a suggested fix for each report and Error Prone's patch mode writes a @SuppressWarnings("NullAway") at each one. The check can then be promoted to error immediately, leaving the suppressions as a backlog to work down.
Pass -XepOpt:NullAway:SuggestSuppressions=true together with Error Prone's patch mode:
-XepOpt:NullAway:SuggestSuppressions=true -XepPatchChecks:NullAway -XepPatchLocation:IN_PLACE
Two constraints apply before you run it:
- Patch mode does not work with NullAway in Error Prone versions after 2.25.0 and before 2.37.0; see Compatibility.
-
-XepOpt:NullAway:AutoFixSuppressionCommentwrites a comment beside each inserted suppression, so a later reader can tell this batch from a deliberate suppression. Its entry has the constraints on the value.
Suppressing Warnings covers the suppression mechanisms themselves, including castToNonNull, which narrows a suppression to one expression.
This migration replaces the AnnotatedPackages prefixes with @NullMarked annotations in the source, in three steps, and requires NullAway 0.12.3 or later. JSpecify tools and other nullness checkers read the annotations; they do not read the prefixes.
- Add
@NullMarkedto every package or class that theAnnotatedPackagesprefixes covered. Apackage-info.javaper package is the usual form.AnnotatedPackagesis still the configured setting at this point, and@NullMarkedcode is treated as annotated whether or not a prefix covers it, so this step changes nothing on its own. - Turn on the
RequireExplicitNullMarkingchecker at warning level, with-Xep:RequireExplicitNullMarking:WARN. It reports every top-level class that is not itself@NullMarkedor@NullUnmarkedand whose package and module are not either. The check reads noAnnotatedPackagessetting, so its report also names classes the prefixes never covered; the ones inside the prefixes are what step 1 missed. - Replace
AnnotatedPackageswith-XepOpt:NullAway:OnlyNullMarked=true. The two cannot both be passed. Requires NullAway 0.12.3 or later.
A class that ends up neither @NullMarked nor covered by a prefix is not checked, and nothing reports it. Step 2 finds those classes before step 3 removes the prefixes.
JSpecify mode adds checking of nullability inside generic types and arrays. It is a larger step than the previous two, because it reports errors that no earlier configuration could report.
- Check the
javacrequirement first: JDK 22 or later, or-XDaddTypeAnnotationsToSymbol=true. NullAway fails the build rather than checking silently; see Supported JDK versions. - Turn on
-XepOpt:NullAway:JSpecifyMode=trueat warning level and read the count. Expect new reports, especially at calls into Guava and into generic APIs; Error Messages covers the JSpecify-mode errors, and JSpecify and Guava covers what an upgraded Guava adds. - Annotate type arguments where the reports call for it, using
@Nullablein type-use position. - Add
-XepOpt:NullAway:JSpecifyExperimental=trueonce step 3 stops producing new reports. It turns on the JDK nullness models, wildcard support, and warnings when inference fails for a generic method call. NullAway expects to enable it by default in a future release.
Getting NullAway running
Writing the annotations
When NullAway reports something
Internals