Skip to content

Option that loads nullness information of JDK package#1472

Open
haewiful wants to merge 8 commits intouber:masterfrom
haewiful:jdk-astubx
Open

Option that loads nullness information of JDK package#1472
haewiful wants to merge 8 commits intouber:masterfrom
haewiful:jdk-astubx

Conversation

@haewiful
Copy link
Contributor

@haewiful haewiful commented Feb 15, 2026

This pull request adds some nullness check support for modules in the JDK package.

  • Adds the astubx file that contains the nullness information for the modules in the JDK package.
  • Adds an option NullAway:JDKInferEnabled that lets the users decide whether to load the astubx file to NullAway.

Some related PRs are #1333.

The unit tests that are added to LibraryModelsHandlerTest.java file.

Summary by CodeRabbit

  • New Features

    • Added a configuration flag to enable JDK inference, allowing optional null-safety checks for JDK APIs and conditional loading of JDK library models.
  • Bug Fixes / Behavior

    • Library model loading now respects the new JDK inference setting and is loaded only when enabled.
  • Tests

    • Added tests validating JDK inference model loading and non-loading behavior.

@haewiful haewiful marked this pull request as ready for review February 15, 2026 04:39
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 15, 2026

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

💤 Files selected but had no reviewable changes (1)
  • nullaway/src/main/resources/output.astubx

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

Adds a new JDK inference configuration flag and wiring throughout the codebase. Introduces isJDKInferEnabled() to the Config API and implements it in DummyOptionsConfig and ErrorProneCLIFlagsConfig (with a new FL_JDK_ENABLED flag and jdkInferEnabled field). LibraryModelsHandler now conditionally loads external stubx models when isJarInferEnabled() or isJDKInferEnabled() is true, and ExternalStubxLibraryModels constructor now accepts two booleans controlling Jar and JDK stub loading. Two unit tests were added to validate JDK astubx loading behavior.

Possibly related PRs

Suggested reviewers

  • yuxincs
  • msridhar
🚥 Pre-merge checks | ✅ 3 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.08% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Option that loads nullness information of JDK package' accurately summarizes the main change: introducing a new configuration option (NullAway:JDKInferEnabled) that enables loading JDK nullness data, which is the primary objective of the PR.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into master

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@nullaway/src/main/java/com/uber/nullaway/handlers/LibraryModelsHandler.java`:
- Line 1564: The constructor ExternalStubxLibraryModels(boolean
isJarInferEnabled, boolean isJDKInferEnabled) uses two positional booleans that
are easy to swap; change the API to accept a descriptive config object or
factory so callers pass named fields. Create a small value class (e.g.,
LibraryInferOptions or InferConfig) with boolean fields jarInferEnabled and
jdkInferEnabled, update ExternalStubxLibraryModels to take that single config
parameter, and update the existing call site to construct and pass the config
(or alternatively add clearly named static factory methods on
ExternalStubxLibraryModels like createWith(jarEnabled, jdkEnabled)). Ensure the
constructor and any usages are updated consistently.
- Around line 1588-1600: Fix the typo in the comment inside LibraryModelsHandler
near the JDK astubx loading block: change "infered" to "inferred" in the comment
that references hardcoded loading of stubx files when isJDKInferEnabled (the
block using getClass().getClassLoader().getResourceAsStream("output.astubx") and
cacheUtil.parseStubStream). Do not change resource names or logic—only update
the comment wording.

private final Map<String, SetMultimap<Integer, NestedAnnotationInfo>> nestedAnnotationInfo;

ExternalStubxLibraryModels() {
ExternalStubxLibraryModels(boolean isJarInferEnabled, boolean isJDKInferEnabled) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Constructor now accepts two separate booleans — consider clarity.

Two positional boolean parameters (isJarInferEnabled, isJDKInferEnabled) can be accidentally swapped at call sites without a compiler error. This is a minor readability concern for now since there's only one call site (Line 483), but worth noting.

🤖 Prompt for AI Agents
In `@nullaway/src/main/java/com/uber/nullaway/handlers/LibraryModelsHandler.java`
at line 1564, The constructor ExternalStubxLibraryModels(boolean
isJarInferEnabled, boolean isJDKInferEnabled) uses two positional booleans that
are easy to swap; change the API to accept a descriptive config object or
factory so callers pass named fields. Create a small value class (e.g.,
LibraryInferOptions or InferConfig) with boolean fields jarInferEnabled and
jdkInferEnabled, update ExternalStubxLibraryModels to take that single config
parameter, and update the existing call site to construct and pass the config
(or alternatively add clearly named static factory methods on
ExternalStubxLibraryModels like createWith(jarEnabled, jdkEnabled)). Ensure the
constructor and any usages are updated consistently.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
nullaway/src/main/java/com/uber/nullaway/handlers/LibraryModelsHandler.java (2)

568-586: ⚠️ Potential issue | 🟡 Minor

Wrap the Android InputStream in try-with-resources to prevent resource leaks.

The InputStream obtained from the Android model class loader at line 1570 is never closed. Although parseStubStream does not close the stream internally, the JDK loading pattern at line 1590 correctly uses try-with-resources. Apply the same pattern to the Android code for consistency and to prevent the stream from leaking if parseStubStream throws an exception.

Proposed fix
       if (isJarInferEnabled) {
         try {
-          InputStream androidStubxIS =
-              Class.forName(ANDROID_MODEL_CLASS)
-                  .getClassLoader()
-                  .getResourceAsStream(ANDROID_ASTUBX_LOCATION);
-          if (androidStubxIS != null) {
-            cacheUtil.parseStubStream(androidStubxIS, "android.jar: " + ANDROID_ASTUBX_LOCATION);
-            astubxLoadLog("Loaded Android RT models.");
+          try (InputStream androidStubxIS =
+              Class.forName(ANDROID_MODEL_CLASS)
+                  .getClassLoader()
+                  .getResourceAsStream(ANDROID_ASTUBX_LOCATION)) {
+            if (androidStubxIS != null) {
+              cacheUtil.parseStubStream(androidStubxIS, "android.jar: " + ANDROID_ASTUBX_LOCATION);
+              astubxLoadLog("Loaded Android RT models.");
+            }
           }
         } catch (ClassNotFoundException e) {

588-600: ⚠️ Potential issue | 🟠 Major

Generic resource name output.astubx risks classpath collisions.

The resource name "output.astubx" is not namespaced, so any other JAR on the classpath with the same resource name could shadow or be loaded instead of the intended JDK nullness data. Consider using a more specific name (e.g., "com/uber/nullaway/jdk-nullness.astubx") to avoid ambiguity.

The loading logic itself (try-with-resources, null check, exception handling) is well-structured.

#!/bin/bash
# Check how/where output.astubx is generated and placed
echo "=== Searching for output.astubx references ==="
rg -n "output\.astubx" --type-not class -C 2

echo ""
echo "=== Checking resource directories ==="
fd "output.astubx" --type f

echo ""
echo "=== Checking build configs for resource placement ==="
rg -n "output\.astubx" -g "*.gradle*" -g "*.xml" -C 3

@codecov
Copy link

codecov bot commented Feb 15, 2026

Codecov Report

❌ Patch coverage is 53.57143% with 13 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.42%. Comparing base (09b39c9) to head (146c824).

Files with missing lines Patch % Lines
...m/uber/nullaway/handlers/LibraryModelsHandler.java 48.00% 13 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master    #1472      +/-   ##
============================================
- Coverage     88.46%   88.42%   -0.04%     
- Complexity     2757     2760       +3     
============================================
  Files            99       99              
  Lines          9196     9210      +14     
  Branches       1847     1850       +3     
============================================
+ Hits           8135     8144       +9     
- Misses          521      526       +5     
  Partials        540      540              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments