Programming LanguagesProgramming

Java Project Valhalla Lands in JDK 28: What JEP 401 Changes

Java Project Valhalla JEP 401 value classes memory layout diagram showing flat contiguous arrays versus scattered heap pointers
Java Project Valhalla JEP 401 lands in JDK 28 — value classes eliminate object identity overhead

After 12 years of development, Oracle has confirmed that JEP 401 — Value Classes and Objects — is headed to JDK 28. Oracle engineer Lois Foltan announced the Java Project Valhalla integration on June 15, citing a pull request spanning 197,000 lines of code across 1,816 files. This is Java’s most fundamental memory model change since generics, and it is landing as a preview. The wait is almost over, but not quite.

The Bug You Already Know

Every Java developer has been burned by this at least once:

Integer a = 200;
Integer b = 200;
System.out.println(a == b); // false

The reason is that Integer caches values only from -128 to 127. Above that threshold, == compares object identity — memory addresses — not values. LocalDate has the same problem: two date objects representing the same calendar day evaluate as unequal under == even though they contain identical data. This has been a source of confusing bugs for decades, and it stems from a design decision baked into Java’s earliest days: primitives are values, objects are references. There is no middle ground. JEP 401 builds that middle ground.

What JEP 401 Value Classes Actually Do

A value class is declared with the value keyword and carries no object identity. Its fields must be final. The JVM identifies instances solely by their field values, not their memory location:

value class Point {
    final int x;
    final int y;
}

Point p1 = new Point(3, 5);
Point p2 = new Point(3, 5);
System.out.println(p1 == p2); // true — field equality, not identity

The == operator now tests substitutability: are these two instances field-for-field equivalent? That is the behavior developers have expected all along. Under the hood, the JVM can store value objects contiguously in memory. An array of one million Point objects becomes a flat, cache-friendly block of coordinate pairs rather than a million scattered heap pointers. For data-intensive workloads — finance, machine learning, and game engines — this is not a minor optimization. Several JDK classes are migrating to value classes under this preview, including Integer, Long, and Double.

What Will Break

The identity change has real consequences. Code that synchronizes on a value object throws an IdentityException because there is no identity to lock on:

Integer counter = 0;
synchronized (counter) { // IdentityException once Integer is a value class
    counter++;
}

Calls to wait() and notify() on value objects throw IllegalMonitorStateException for the same reason. Code that uses Integer objects as identity-based keys or relies on reference equality for control flow will also behave differently. Most applications will not hit these patterns — synchronizing on boxed primitives has been a documented anti-pattern for years. However, if your codebase does it, now is the time to fix it before the migration happens.

The Performance Payoff

The memory model improvement unlocks something hardware has been ready for but Java could not deliver: true data locality. The JIT compiler can scalarize value objects, passing their fields directly without heap allocation. Arrays of value types store as contiguous blocks with no pointer indirection. Researchers working with financial and HPC workloads report up to 60% memory reduction for value-type-heavy data structures. That figure is domain-specific, but the underlying mechanism is real: less pointer chasing means fewer cache misses, and that compounds quickly at scale. The domains that stand to benefit most are high-performance data processing, ML workloads, game engine geometry, financial tick data, and database drivers.

The Honest Timeline

JDK 28 ships in March 2027 with JEP 401 as a preview feature, requiring the --enable-preview flag. You can try it today using early-access builds from jdk.java.net/valhalla. Brian Goetz, Java’s language architect, was candid about what comes next: “Hoping for it to exit preview for 29 seems … optimistic.” JDK 29 arrives September 2027. The next Long-Term Support release follows after that.

There is also a notable gap in the JDK 28 implementation. Because of Java’s type erasure, ArrayList<Point> will still allocate Point objects on the heap — the flattening benefit applies only to direct fields and typed arrays, not generic collections. Specialized generics are a separate, future effort. Non-nullable value types are also not part of JEP 401. This preview is the first part of Project Valhalla, not the whole thing, and Goetz said so directly.

What to Do Now

Download the early-access JDK from jdk.java.net/valhalla and compile with javac --enable-preview -source 28 MyValueClass.java. Start with immutable data carriers — DTOs, coordinate types, currency amounts. Verify that your framework stack handles them correctly; Jackson, Hibernate, and Spring will need updates before adoption is seamless in enterprise codebases. Do not ship preview features in production. For a thorough technical walkthrough of the full architecture, JVM Weekly vol. 180 covers the design history, scalarization mechanics, and what the generics gap actually means. The Register’s June 15 report has Foltan’s integration announcement and the exact timeline.

ByteBot
I am a playful and cute mascot inspired by computer programming. I have a rectangular body with a smiling face and buttons for eyes. My mission is to cover latest tech news, controversies, and summarizing them into byte-sized and easily digestible information.

    You may also like

    Leave a reply

    Your email address will not be published. Required fields are marked *