Open-source project
uber/NullAway avatar
uber/NullAway

NullAway: Fast Annotation-Based Null Checking for Java Builds

A tool to help eliminate NullPointerExceptions (NPEs) in your Java code with low build-time overhead.

4,104 stars369 forksJavaMIT

At a glance

What is it?
NullAway is an Error Prone plugin that adds type-based null checking to Java builds. It targets NPEs with low overhead, but requires annotation discipline and a specific build setup.
Who is it for?
Adopt NullAway if you have a Java codebase with disciplined annotation usage, can run Error Prone on every build, and accept its practical scope: it catches most NPEs, not all. Do not adopt it if you cannot add @Nullable annotations consistently, if your build uses ancient Dagger versions, or if you expect full null-safety without annotation burden.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Java, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The Problem NullAway Targets

NullPointerExceptions are a common source of runtime failures in Java. NullAway aims to reduce them by checking, at compile time, that any pointer dereferenced in your code cannot be null. It does this based on annotations: you add @Nullable to fields, parameters, and return values that may be null. Then NullAway performs local, type-based checks to ensure that non-null pointers are never dereferenced unsafely. The intended audience is Java developers who want to catch most NPEs without the overhead of a full formal verification tool. The README explicitly says it does not prevent all possible NPEs, but catches most of those observed in production while imposing a reasonable annotation burden. This is a practical trade-off, not a promise of total safety.

How NullAway Works: A Plugin to Error Prone

NullAway is built as a plugin to Error Prone, which is a static analysis framework that hooks into the Java compiler. It runs on every build of your code, which is why the project emphasizes low build-time overhead. The README reports that overhead is usually less than 10% in their measurements. That number comes from the project itself, not from our testing, but it gives a sense of the design goal. The mechanism is type-based and local: it tracks nullability through assignments, method calls, and conditionals, but does not do interprocedural analysis across the whole program. This is similar to the type-based null checking in Kotlin and Swift, and also comparable to the Checker Framework and Eradicate. Because it is a plugin, it integrates with Error Prone's existing infrastructure, including its severity levels and configuration flags. The plugin approach means you must already use Error Prone, which is a prerequisite that shapes who can adopt NullAway.

Getting NullAway Running in a Gradle Build

The README gives a concrete Gradle configuration for non-Android Java projects. You add the net.ltgt.errorprone plugin, then declare a dependency on com.uber.nullaway:nullaway with a specific version, plus a source of nullability annotations. JSpecify is recommended, but other annotations like AndroidX or JetBrains are also allowed. You also need com.google.errorprone:error_prone_core. In the JavaCompile task, you set the NullAway check to ERROR severity and pass the option NullAway:AnnotatedPackages, for example com.uber. This tells NullAway which packages are annotated and should be checked. NullAway requires exactly one of AnnotatedPackages or OnlyNullMarked to run, so you must choose one. The README also notes that you can use options.errorprone.disableAllChecks to run NullAway without other Error Prone checks, which is useful for a trial run. For Android, the configuration differs because Gradle Error Prone Plugin 3.0.0 and later do not support Android; you need extra setup or an older plugin version, and you can use androidx.annotation.Nullable instead of JSpecify.

Handling Generated Code and Dagger

A significant practical issue is generated code. Annotation processors like Dagger and AutoValue generate code into the same package namespace as your own code. If NullAway is set to ERROR, errors in generated code will block the build. The README suggests disabling Error Prone on generated code entirely using the -XepExcludedPaths option, which requires you to know the directory where generated code lives. This is a blunt solution: it means generated code is not checked at all, which could allow null-safety issues to slip through in that code. For Dagger specifically, the README warns that versions older than 2.12 have bad interactions with NullAway, so you must update to Dagger 2.12 or later. This is a concrete constraint that could affect existing projects. If you have a codebase with heavy annotation processing, budget time to configure excluded paths and verify that generated code does not cause false positives.

Limitations and When NullAway Is the Wrong Tool

NullAway is not a complete null-safety solution. The README states it does not prevent all possible NPEs, which is a genuine limitation. It requires that you add @Nullable annotations consistently; if your codebase lacks them, the tool cannot do much. The local, type-based checks mean it may miss issues that require deeper interprocedural analysis. Also, NullAway only checks packages you explicitly annotate via AnnotatedPackages or OnlyNullMarked, so unannotated code is not checked. This is by design, but it means the tool is ineffective if you cannot classify your codebase. Furthermore, the requirement to run Error Prone is a barrier: if your build does not already use Error Prone, you must adopt that first. For small projects or quick prototypes, the setup overhead may outweigh the benefit. For codebases with extensive reflection or dynamic code generation, type-based checking may be insufficient. In such cases, a runtime null-checking library or a more powerful static analyzer might be a better fit.

Alternatives: Checker Framework and Eradicate

The README names two direct alternatives: the Checker Framework and Eradicate. The Checker Framework is a more comprehensive static analysis tool that can perform interprocedural and more precise null checks, but it is typically slower and requires more annotation effort. Eradicate is part of Facebook's Infer, which does a different kind of analysis: it uses separation logic and can catch a broader range of bugs, but it runs as a separate tool, not as a compiler plugin. The key difference in approach is that NullAway trades precision for speed and integration. It runs on every build with low overhead, making it suitable for continuous checking, whereas the Checker Framework might be run less frequently due to its cost. Eradicate is not a build-time plugin in the same way; it is a separate analysis pass. If you need deep null-safety guarantees, the Checker Framework or Eradicate may be more appropriate, but they come with different trade-offs in annotation burden and analysis time. NullAway's advantage is its simplicity and speed, which is why it is positioned as a practical tool for production code.

Maintenance, Upgrade Cost, and License

NullAway is under active development, with recent releases including v0.14.0, v0.13.8, and v0.13.7. The project is not archived, and the last push was in August 2026. This suggests ongoing maintenance, but it also means you need to track version updates. Upgrading NullAway may require updating Error Prone as well, since NullAway requires Error Prone 2.36.0 or higher. The README recommends using the most recent JDK when building with JSpecify mode, which implies that newer JDKs may be needed for full compatibility. The configuration is straightforward, but the dependency on Error Prone and annotation libraries adds moving parts. The license is MIT, which is permissive and allows commercial use without restrictions, but you should review the license text for any specific terms. There is no mention of a separate support contract, so you rely on the community and the project's issue tracker. For a production adoption, you should plan to test each NullAway upgrade in a staging build, because changes in analysis behavior can introduce new errors or change existing ones.

Editorial conclusion

Adopt NullAway if you have a Java codebase with disciplined annotation usage, can run Error Prone on every build, and accept its practical scope: it catches most NPEs, not all. Do not adopt it if you cannot add @Nullable annotations consistently, if your build uses ancient Dagger versions, or if you expect full null-safety without annotation burden. Before adopting, verify your Error Prone version is 2.36.0 or higher, your JDK is 17 or newer, and that you can exclude generated code from checks. Also confirm whether you will use JSpecify mode, which the docs recommend building with the most recent JDK. The trade-off is clear: NullAway trades completeness for speed and practicality, so it fits teams that want a cheap, incremental check rather than a formal proof.

Official sources

  1. Official README
  2. Project repository
  3. Release notes
Community notes

Community notes