Fundamentals 13 min read

Why Java’s final Keyword Guarantees Thread Safety – Deep Dive

This article explains the semantics of Java's final keyword, how the compiler and JVM enforce immutability and memory‑barrier rules, and why final fields provide thread‑safe, write‑once‑read‑many behavior for both instance and static variables.

Xiaokun's Architecture Exploration Notes
Xiaokun's Architecture Exploration Notes
Xiaokun's Architecture Exploration Notes
Why Java’s final Keyword Guarantees Thread Safety – Deep Dive

Final Keyword Semantics and Usage

The compiler may move reads of final fields across synchronization barriers and cache final values in registers, making them immutable across threads.

Thread‑Safety of Final Fields

Final fields are effectively immutable; writes are only allowed in constructors, and all threads see the final value after construction.

The Happen‑Before relationship guarantees that the final value is visible to all threads without reordering.

Usage Model (write‑once, read‑many)

Final fields are assigned in the constructor; no other thread may see a partially constructed object.

This ensures that any thread reading the object observes the fully initialized final fields.

Code Example and Analysis

<code>public class FinalClass {
    public final int i;
    public int j;
    public final DefineFinalObject defineFinalObject;
    static FinalClass finalClass;

    public FinalClass() {
        // i = 4; // compile‑time error if placed inside try
        // defineFinalObject = new DefineFinalObject();
        try {
            j = 9; // allowed because j is not final
        } catch (Exception e) {}
    }

    static void writer() {
        finalClass = new FinalClass();
        System.out.println("have init FinalClass");
    }

    static void reader() {
        if (finalClass != null) {
            int x = finalClass.i;
            int y = finalClass.j;
            System.out.printf("get x = %d, and y = %d", x, y);
        }
    }
}
</code>

The compiler forbids writing to i inside a try block and allows writing to j . Reads of i before its assignment cause a compile‑time error, enforcing the write‑once rule.

Final vs. static Final

<code>public class FinalSharedClass {
    public final static int num;
    public static int x;
    public final static DefineFinalObject defineFinalObject;

    static {
        num = 10;
        defineFinalObject = new DefineFinalObject();
        System.out.printf("have finished static code for num=%d and obj=%s...\n", num, defineFinalObject);
    }

    static void writer() {
        // num = 20; // compile‑time error
        // defineFinalObject = new DefineFinalObject(); // compile‑time error
        x = 10;
        defineFinalObject.setAge(10);
    }

    static void reader() {
        System.out.printf("read final static num: %d \n", num);
        System.out.printf("read final static defineFinalObject: %s \n", defineFinalObject);
        System.out.printf("read static x: %d \n", x);
    }
}
</code>

Static final fields are initialized in a static block, which runs once when the class is loaded, guaranteeing that all threads see the initialized value.

Implementation of Final Semantics

On AArch64 the JVM inserts a StoreStore memory barrier before a constructor returns, ensuring that writes to final fields become visible only after the barrier.

Volatile vs. Final Memory Barriers

Volatile writes use a StoreLoad barrier, while final writes use a StoreStore barrier. The former prevents reordering of subsequent reads; the latter prevents reordering of preceding writes.

Summary of the Specification

Final fields are assigned in constructors (or static blocks) and cannot be modified afterwards.

Reading a final field requires first obtaining a reference to the containing object.

Static final fields act as constants; System.in/out/err are special cases that remain mutable via System.setIn, etc.

In bytecode, final fields carry the ACC_FINAL flag (0x1000).

JavaConcurrencyThread SafetyMemory Modelfinalstatic final
Xiaokun's Architecture Exploration Notes
Written by

Xiaokun's Architecture Exploration Notes

10 years of backend architecture design | AI engineering infrastructure, storage architecture design, and performance optimization | Former senior developer at NetEase, Douyu, Inke, etc.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.