Skip to content

fix: resolves mutation warning#2545

Open
wfouche wants to merge 10 commits into
jbangdev:mainfrom
wfouche:dev/final-methods-java26
Open

fix: resolves mutation warning#2545
wfouche wants to merge 10 commits into
jbangdev:mainfrom
wfouche:dev/final-methods-java26

Conversation

@wfouche

@wfouche wfouche commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Closes #2542

@maxandersen , @quintesse - given the discussion in #2430 , the most practical interim solution is to remove the final modifiers from serializable classes. The additional option previously added to the manifest.mf file only works when JBang is started with java -jar jbang.jar ...., and does not work otherwise.

I've commented out (/* final */) the final modifiers and have not removed them.

Summary by CodeRabbit

  • Chores
    • Simplified JAR invocation mechanism across platform-specific launch scripts for streamlined execution.

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto reviews are limited based on label configuration.

🏷️ Required labels (at least one) (1)
  • ai-review

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: bbc792f9-594d-41f7-b184-a8bd9cf613ae

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

Walkthrough

All three JBang launcher scripts (jbang, jbang.cmd, jbang.ps1) replace the -classpath <jarPath> dev.jbang.Main invocation pattern with -jar <jarPath> in both the JDK activation step and the main JAR execution path. No other control flow is changed.

Changes

Switch launcher scripts to -jar invocation

Layer / File(s) Summary
Replace -classpath with -jar in all three launchers
src/main/scripts/jbang, src/main/scripts/jbang.cmd, src/main/scripts/jbang.ps1
Each script is updated in two locations (JDK activation step and main JAR execution path) to invoke the JBang JAR via java -jar <jarPath> instead of java -classpath <jarPath> dev.jbang.Main, delegating entry-point resolution to the JAR manifest.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Suggested labels

ai-review

Suggested reviewers

  • maxandersen
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive Title is vague and non-descriptive. 'Mutation warning' alone does not clearly convey what changed or which components were modified. Replace with a more specific title that mentions the key change, such as 'fix: use java -jar in startup scripts to resolve mutation warnings' or similar.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Changes fully address issue #2542 by modifying startup scripts to use -jar invocation, ensuring manifest options are processed and final field mutation warnings are resolved.
Out of Scope Changes check ✅ Passed All changes are directly scoped to issue #2542: modifications to jbang, jbang.cmd, and jbang.ps1 scripts to use -jar invocation for proper manifest processing.

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


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.

@wfouche

wfouche commented Jun 20, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jun 20, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/java/dev/jbang/catalog/Alias.java`:
- Around line 63-66: The JavaAgent inner class within the Alias class has final
fields (agentRef and options) that are annotated with `@SerializedName`, causing
Java 26 final-field mutation warnings when Gson reflectively mutates them during
deserialization. Locate the JavaAgent inner class and remove the final keyword
from both the agentRef field and the options field to match the pattern already
applied to the outer Alias class fields.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 87332c72-668a-42c0-b921-ddd0759f9c5a

📥 Commits

Reviewing files that changed from the base of the PR and between e1d7e22 and f619637.

📒 Files selected for processing (5)
  • build.gradle
  • src/main/java/dev/jbang/catalog/Alias.java
  • src/main/java/dev/jbang/catalog/Catalog.java
  • src/main/java/dev/jbang/catalog/CatalogRef.java
  • src/main/java/dev/jbang/catalog/Template.java

Comment on lines +63 to +66
@JsonAdapter(Catalog.SkipEmptyListSerializer.class)
public final List<JavaAgent> javaAgents;
public /* final */ List<JavaAgent> javaAgents;
@JsonAdapter(Catalog.SkipEmptyListSerializer.class)
public final List<String> docs;
public /* final */ List<String> docs;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify remaining final fields in Gson-bound catalog DTOs that may still be reflectively written.
# Expected: no remaining DTO fields that are both Gson-mapped and final in this serialization path.

rg -n -C2 --type=java 'class JavaAgent|`@SerializedName`|public\s+final\s+String\s+agentRef|public\s+final\s+String\s+options' src/main/java/dev/jbang/catalog/Alias.java
rg -n --type=java 'public\s+final\s+' src/main/java/dev/jbang/catalog/Catalog.java src/main/java/dev/jbang/catalog/CatalogRef.java src/main/java/dev/jbang/catalog/Template.java src/main/java/dev/jbang/catalog/Alias.java

Repository: jbangdev/jbang

Length of output: 2462


Remove final from Alias.JavaAgent fields to prevent reflective mutation warnings.

The inner JavaAgent class still has actual final fields (agentRef at line 71 and options at line 73) that are Gson-bound via @SerializedName annotations. Gson will reflectively mutate these fields during deserialization, which triggers Java 26 final-field mutation warnings. Apply the proposed patch to remove final from both fields in the JavaAgent class to match the fix applied to the outer Alias class.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/dev/jbang/catalog/Alias.java` around lines 63 - 66, The
JavaAgent inner class within the Alias class has final fields (agentRef and
options) that are annotated with `@SerializedName`, causing Java 26 final-field
mutation warnings when Gson reflectively mutates them during deserialization.
Locate the JavaAgent inner class and remove the final keyword from both the
agentRef field and the options field to match the pattern already applied to the
outer Alias class fields.

@maxandersen

Copy link
Copy Markdown
Collaborator

-1 on making the code weaker because of openjdk dumb printing warning behaviours.

i haven't looked yet but what stops us from running jbang with -jar and it will pick up the flag from there?

@wfouche

wfouche commented Jun 20, 2026

Copy link
Copy Markdown
Contributor Author

Given that ${jarPath} always points to the the jbang.jar file, changing

    # Run JAR
    output=$(CLICOLOR_FORCE=1 "${JAVA_EXEC}" ${JBANG_JAVA_OPTIONS} -classpath "${jarPath}" dev.jbang.Main "$@")
    err=$?

to

    # Run JAR
    output=$(CLICOLOR_FORCE=1 "${JAVA_EXEC}" ${JBANG_JAVA_OPTIONS} -jar "${jarPath}" "$@")
    err=$?

resolves the mutation warning without having to remove the final methods. I'll rework the PR and change the jbang, jbang.cmd, and jbang.ps1 scripts and change -classpath "${jarPath}" dev.jbang.Main to -jar "${jarPath}"

@wfouche

wfouche commented Jun 20, 2026

Copy link
Copy Markdown
Contributor Author

-1 on making the code weaker because of openjdk dumb printing warning behaviours.

@maxandersen , the latest update fully resolves the issue. Thanks for the push back on the original proposal :-)

@wfouche

wfouche commented Jun 20, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 20, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@maxandersen

Copy link
Copy Markdown
Collaborator

one thing to check is if we ever call jbang with a custom classpath - i.e. during integration runs ...here I guess there will be an issue too but its much less visible.

@wfouche

wfouche commented Jun 20, 2026

Copy link
Copy Markdown
Contributor Author

one thing to check is if we ever call jbang with a custom classpath - i.e. during integration runs

If you are referring to the itests, I just ran all of them and they seem fine. They all just call jbang directly. I had jbang resolve to the one in build/install/jbang/bin/jbang and ran all tests with Java 26.0.1

@wfouche

wfouche commented Jun 27, 2026

Copy link
Copy Markdown
Contributor Author

@maxandersen , this PR is ready to be reviewed (hopefully merged). :-)

@wfouche

wfouche commented Jul 5, 2026

Copy link
Copy Markdown
Contributor Author

Testing with the latest early-access release still produces the following output when using Java 26.

$ java -version
openjdk version "26.0.1" 2026-04-21
OpenJDK Runtime Environment Temurin-26.0.1+8 (build 26.0.1+8)
OpenJDK 64-Bit Server VM Temurin-26.0.1+8 (build 26.0.1+8, mixed mode, sharing)

$ jbang version
0.139.3.16

$ jbang run hello@jbangdev JBang
WARNING: Final field catalogRef in class dev.jbang.catalog.CatalogRef has been mutated reflectively by class com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$2 in unnamed module @475e586c (file:/home/wfouche/.jbang/bin/jbang.jar)
WARNING: Use --enable-final-field-mutation=ALL-UNNAMED to avoid a warning
WARNING: Mutating final fields will be blocked in a future release unless final field mutation is enabled
Hello JBang

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.

Running JBang with Java 26 results in final field mutated warning

2 participants