Skip to content

Prepare for final field mutation warning under Java 26 #2991

@TheDGOfficial

Description

@TheDGOfficial

Gson version

2.13.2

Java / Android version

openjdk version "26" 2026-03-17
OpenJDK Runtime Environment (build 26+35-2893)
OpenJDK 64-Bit Server VM (build 26+35-2893, mixed mode, sharing)

Used tools

  • Maven; version:
  • Gradle; version:
  • ProGuard (attach the configuration file please); version:
  • ...

Description

A final field mutation warning appears when running under Java 26.

Expected behavior

No warnings expected.

Actual behavior

Warning appears.

Reproduction steps

import com.google.gson.Gson;

class ClassWithFinalField {
    final String finalField;

    ClassWithFinalField(String s) {
        finalField = s;
    }

    void print() {
        IO.println(finalField);
    }
}

void main() {
    new Gson().fromJson(
        """
        {"finalField":"Hello, world!"}
        """
    , ClassWithFinalField.class).print();
}
  1. Run with Java 25; no warnings, mutation works.
  2. Run with Java 26; warnings emitted, mutation still works but is going to be disallowed in a future release.

To run, download gson 2.13.2 jar from maven central, save the code above to a file named TestFinalFieldModification.java, and run the following:

java -cp gson-2.13.2.jar TestFinalFieldModification.java

For Java 26, replace java with the path to java 26 binary, like ./jdk-26/bin/java

*Java 26 is still in early access but is going to reach general availability in approx. 1 week from now on so I wanted to create the issue in advance.

Exception stack trace

WARNING: Final field finalField in class TestFinalFieldModification$ClassWithFinalField has been mutated reflectively by class com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$2 in unnamed module @59fd97a8 (file:/home/mustafa/%c4%b0ndirilenler/gson-2.13.2.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

When using --illegal-final-field-mutation=debug:

Final field finalField in class TestFinalFieldModification$ClassWithFinalField has been mutated reflectively by class com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$2 in unnamed module @795cd85e (file:/home/mustafa/%c4%b0ndirilenler/gson-2.13.2.jar)
	at java.base/java.lang.reflect.Field.postSetFinal(Field.java:1534)
	at java.base/java.lang.reflect.Field.setFinal(Field.java:1449)
	at java.base/java.lang.reflect.Field.set(Field.java:909)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$2.readIntoField(ReflectiveTypeAdapterFactory.java:282)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$FieldReflectionAdapter.readField(ReflectiveTypeAdapterFactory.java:559)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:517)
	at com.google.gson.Gson.fromJson(Gson.java:1358)
	at com.google.gson.Gson.fromJson(Gson.java:1259)
	at com.google.gson.Gson.fromJson(Gson.java:1169)
	at com.google.gson.Gson.fromJson(Gson.java:1106)
	at TestFinalFieldModification.main(TestFinalFieldModification.java:16)
	at jdk.compiler/com.sun.tools.javac.launcher.SourceLauncher.execute(SourceLauncher.java:262)
	at jdk.compiler/com.sun.tools.javac.launcher.SourceLauncher.run(SourceLauncher.java:138)
	at jdk.compiler/com.sun.tools.javac.launcher.SourceLauncher.main(SourceLauncher.java:76)

When using --illegal-final-field-mutation=deny (going to be the default behaviour in a later release):

Exception in thread "main" java.lang.RuntimeException: Unexpected IllegalAccessException occurred (Gson 2.13.2). Certain ReflectionAccessFilter features require Java >= 9 to work correctly. If you are not using ReflectionAccessFilter, report this to the Gson maintainers.
	at com.google.gson.internal.reflect.ReflectionHelper.createExceptionForUnexpectedIllegalAccess(ReflectionHelper.java:201)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:523)
	at com.google.gson.Gson.fromJson(Gson.java:1358)
	at com.google.gson.Gson.fromJson(Gson.java:1259)
	at com.google.gson.Gson.fromJson(Gson.java:1169)
	at com.google.gson.Gson.fromJson(Gson.java:1106)
	at TestFinalFieldModification.main(TestFinalFieldModification.java:16)
Caused by: java.lang.IllegalAccessException: class com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$2 (in unnamed module @59fd97a8) cannot set final field TestFinalFieldModification$ClassWithFinalField.finalField (in unnamed module @f5ac9e4), unnamed module @59fd97a8 is not allowed to mutate final fields
	at java.base/java.lang.reflect.Field.preSetFinal(Field.java:1504)
	at java.base/java.lang.reflect.Field.setFinal(Field.java:1447)
	at java.base/java.lang.reflect.Field.set(Field.java:909)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$2.readIntoField(ReflectiveTypeAdapterFactory.java:282)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$FieldReflectionAdapter.readField(ReflectiveTypeAdapterFactory.java:559)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:517)
	at com.google.gson.Gson.fromJson(Gson.java:1358)
	at com.google.gson.Gson.fromJson(Gson.java:1259)
	at com.google.gson.Gson.fromJson(Gson.java:1169)
	at com.google.gson.Gson.fromJson(Gson.java:1106)
	at TestFinalFieldModification.main(TestFinalFieldModification.java:16)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
	at java.base/java.lang.reflect.Method.invoke(Method.java:565)
	at jdk.compiler/com.sun.tools.javac.launcher.SourceLauncher.execute(SourceLauncher.java:262)
	at jdk.compiler/com.sun.tools.javac.launcher.SourceLauncher.run(SourceLauncher.java:138)
	at jdk.compiler/com.sun.tools.javac.launcher.SourceLauncher.main(SourceLauncher.java:76)

References

JEP 500: Prepare to Make Final Mean Final

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions