Skip to main content

requireNullMarked

Category: Rules Reference
Scope: Classes, Interfaces, Enums, Annotations, Packages
Purpose: Ensures that classes or packages are annotated with @NullMarked to define a clear default nullness context.


What does it check?​

The requireNullMarked rule verifies that classes (and other types like interfaces and enums) or packages are properly annotated with @NullMarked, unless explicitly excluded.

Without @NullMarked, types may have unspecified nullness, which can lead to ambiguity or bugs.


Why is it important?​

  • Enforces explicit nullness context at the class or package level.
  • Helps avoid missing nullability specifications on fields, methods, and parameters.
  • Provides a way to set nullness context for entire packages.

Examples​

❌ Invalid Example: Class without @NullMarked​

package com.example;

public class UserProfile {

private String username;
private String email;
}

Problem detected:

[ERROR] com.example.UserProfile: Missing @NullMarked annotation on class.

✅ Valid Example: Class with @NullMarked​

package com.example;

import org.jspecify.annotations.NullMarked;

@NullMarked
public class UserProfile {

private String username;
private String email;
}

How to configure it?​

You can enable the requireNullMarked rule by adding it to your plugin configuration:


<configuration>
<rules>
<requireNullMarked/>
</rules>
</configuration>

Optional parameters:

ParameterTypeDefaultDescription
exclusionsFileString(none)Path to a text file listing classes to exclude, see Exclusions File Format
exclusionsString(none)Classes or patterns to exclude, defined inline, one per line. Same format as the exclusions file; combined with exclusionsFile if both are set
excludeAnnotationsString(none)Comma-separated list of fully qualified annotation names. Classes with these annotations will be excluded from analysis
onStringCLASSDefine where to require putting the @NullMarked annotation. Allowed values are CLASS, PACKAGE or MODULE, they can be combined with + (e.g. MODULE+PACKAGE) - then every listed location must be annotated

When to enable?​

Recommended for:

  • New projects starting with JSpecify annotations.
  • Projects migrating to explicit nullness declarations.
  • Teams that want to enforce consistent annotation practices during development and in CI/CD pipelines.
  • Projects that prefer package-level nullness declarations (<on>PACKAGE</on>).
  • Modular projects that declare nullness on the module (<on>MODULE</on>).
  • Libraries consumed both from the module path and the class path (<on>MODULE+PACKAGE</on> or <on>MODULE+CLASS</on>) - the module-level annotation is not visible to class path consumers.

Requiring @NullMarked on several locations​


<configuration>
<rules>
<requireNullMarked>
<on>MODULE+PACKAGE</on>
</requireNullMarked>
</rules>
</configuration>

Limitations​

  • Only verifies the presence of @NullMarked.
  • When using <on>CLASS</on>, the rule does not require @NullMarked on package-info.java — it only focuses on types (classes, interfaces, enums, etc.).
  • When using <on>PACKAGE</on>, all packages must have a package-info.java file with @NullMarked.
  • When using <on>MODULE</on>, the project must have a module-info.java file with @NullMarked. A missing module-info is reported as an issue; it can be excluded with the module-info pattern.
  • Annotation-based exclusions only work at the class level, not for individual members or packages.