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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions