Saturday, June 06, 2026

Java 26: Mutating Final Fields Using Reflection

Java 26 introduces a new warning when code uses reflection to mutate final fields. This change comes from JEP 500: Prepare to Make Final Mean Final, and is part of Java’s ongoing move toward stronger integrity and better JVM optimisations. The JVM relies on the assumption that final fields never change in order to perform optimisations such as constant folding and safe object initialisation in concurrent code. However, deep reflection APIs like Field.setAccessible(true) and Field.set(...) have historically allowed any code to mutate final fields at runtime, breaking those guarantees.

Consider the following code that reflectively mutates a final field:

public class Foo {

  final int x;

  Foo() {
    x = 100;
  }

  public static void main(String... args) 
                          throws Exception {

    Foo obj = new Foo();

    System.out.println(obj.x);
    
    java.lang.reflect.Field f =
            Foo.class.getDeclaredField("x");
    f.setAccessible(true);
    f.set(obj, 200); // mutate the final field

    System.out.println(obj.x);
  }
}

In older JDK versions, this would silently mutate the supposedly immutable final field.

In JDK 26, it still works, but produces warnings:

100
WARNING: Final field x in class Foo has been mutated reflectively by class Foo in unnamed module @764c12b6
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
200

In a future JDK release, these operations are expected to fail unless explicitly enabled using --enable-final-field-mutation=ALL-UNNAMED or for specific modules --enable-final-field-mutation=M1,M2.

So, stop mutating final fields! final means final.

Saturday, May 30, 2026

Java 26: Thread.stop() Removed

Java 26 finally removes Thread.stop(), one of the oldest deprecated methods in the JDK!

This method has long been considered inherently unsafe because it does not give the target thread a chance to clean up resources, release locks safely, or complete critical sections of code. If a thread was stopped while mutating shared state, other threads could observe partially updated data and corrupted state.

What should you use instead?

Modern Java code should use cooperative cancellation instead of forcibly terminating threads, to allow them to stop safely at a controlled point in execution. Typically this means:

  • using interruption (Thread.interrupt())
  • checking interruption status
  • using structured concurrency or executors
  • designing tasks to terminate gracefully

Thursday, May 28, 2026

Java 26: Lazy Constants

In my previous post, I wrote about Stable Values introduced in Java 25. Java 26 renames them from Stable Values to Lazy Constants. While the underlying idea remains the same, the new name better reflects the intended use case: immutable values that are initialised lazily. This is a preview language feature.

A Lazy Constant allows you to defer the initialisation of immutable data until it is actually needed, while still allowing the JVM to optimise access to that data as though it were a regular final field.

Here is the example from the previous post, rewritten using a LazyConstant:

public class Controller {

    private final LazyConstant<ExpensiveResource> resource =
            LazyConstant.of(() -> new ExpensiveResource());

    public void process(String request) {
        resource.get().get(request);
    }
}

Initially, the lazy constant is uninitialised. The first call to resource.get() invokes the lambda expression, creates the ExpensiveResource, stores it permanently, and returns it. Subsequent calls simply return the already initialised value. Importantly, the initialisation function is guaranteed to execute only once, even under concurrent access.

Under the hood, the content of a LazyConstant is stored in a non-final field annotated with the JDK-internal @Stable annotation. This tells the JVM that the field will never change after it is written. Due to this guarantee, the JVM can treat the value like a constant, provided that the reference to the stable value is final, and perform constant-folding optimisations, even through multiple layers of stable values.

Thursday, January 01, 2026

fahd.blog in 2025

Happy 2026, everyone!

I'd like to wish everyone a great start to an even greater new year!

In keeping with tradition, here's one last look back at fahd.blog in 2025.

During 2025, I posted 8 new entries on fahd.blog. I am also thrilled that I have more readers from all over the world! Thanks for reading and especially for giving feedback.

Top 3 posts of 2025:

I'm going to be writing a lot more this year, so stay tuned for more great techie tips, tricks and hacks! :)

Related posts: