NewsProgramming Languages

Java Value Classes Land in JDK 28: Project Valhalla Ships

Split-screen illustration showing Java heap pointer model vs value class dense memory layout with blue and white ByteIota branding

Today, July 31, 2026, the JEP 401 pull request merged into the OpenJDK mainline — ending Project Valhalla’s 12-year journey and delivering value classes to Java for the first time. The change targets JDK 28 (expected March 2027) and spans 197,000 lines of code across 1,816 files, led by David Simms with 59 co-authors. Other committers were asked to pause major work during integration. This is the most significant change to Java’s memory model since the language launched in 1995.

The Problem: Java’s Heap Has Always Been Chatty

Every Java object outside the handful of primitives — int, double, char — carries identity. Each instance occupies a unique memory location, tracked by a header and a heap pointer. Two calls to LocalDate.of(2026, 7, 31) return two different objects; == returns false even though they represent the same date. That’s not a quirk — it’s fundamental to Java’s object model. And it’s expensive.

Value classes strip identity entirely. An instance of a value class is distinguished only by its field values, not its memory address. As JVM Weekly put it: “Records fixed the ergonomics of writing small immutable data types; value classes fix what happens to those types at the memory and JIT level.” Records are about syntax convenience. Value classes are about what the JVM does with your data.

The syntax is clean. Declare a value record to get both ergonomics and performance:

value record Point(int x, int y) {}

Point p1 = new Point(3, 4);
Point p2 = new Point(3, 4);
System.out.println(p1 == p2); // true — value equality, not pointer equality

// Enable in JDK 28 preview:
// javac --enable-preview --release 28 Point.java
// java --enable-preview Point

The == behavior alone signals how fundamental this shift is. For more on the other Java change landing today, see JEP 540: Java Gets a Built-In JSON API, No Jackson Needed.

Scalarization and Heap Flattening: Why Java Value Classes Actually Matter

Remove identity from an object and the JVM gains two optimization paths that have been off-limits since 1995. First, scalarization: the JIT decomposes a value object into its raw fields in registers or on the stack. A method receiving a Color value class passes three integer bytes directly — no heap allocation, no pointer dereference. Second, heap flattening: arrays and fields store value data inline. A Color[] of 1 million elements becomes a dense block of 32-bit values instead of 1 million pointers scattering across the heap.

The performance difference is measurable. A benchmark on inside.java summing year values from a 50-million-element LocalDate array showed nearly 3x speedup when LocalDate operated with value semantics. Cache locality is the mechanism: dense memory layouts reduce pointer-chasing and improve CPU cache hit rates. Data-intensive Java workloads — trading systems, game engines, scientific computing — are the primary beneficiaries.

How to Use Java Value Classes in JDK 28 — and One Real Limitation

JEP 401 ships as a preview in JDK 28, disabled by default. Opt in with --enable-preview at both compile and runtime. The value record syntax combines record ergonomics with value class semantics. A standalone value class requires fields be final and cannot be used as a lock object. The new Objects.hasIdentity(obj) API lets you detect identity-free objects programmatically during the transition period.

However, skip the hype about collections. Without specialized generics — a separate JEP, still future work — a List<Point> still boxes each Point onto the heap. Type erasure prevents flattening in generic containers. The 3x speedup applies to arrays and direct fields, not to ArrayList<Point>. Brian Goetz, Java’s Language Architect, was direct about the timeline: “Hoping for it to exit preview for [JDK] 29 seems … optimistic.” Plan for JDK 30 or later before treating value classes as GA. See the full spec at the JEP 401 PR on GitHub and The Next Web’s coverage.

Integer Is Losing Its Identity — Audit Your Sync Code Now

Over time, JDK built-in “value-based classes” — Integer, Long, Double, LocalDate — will migrate to value classes. That migration is intentional and introduces a deliberate breaking change: code synchronizing on boxed primitives will throw exceptions. Value objects have no monitor. Synchronizing on Integer after migration isn’t a runtime warning — it’s a crash.

This is a known anti-pattern, but legacy codebases are full of it. JDK 28’s preview period gives you a one-year runway to audit for synchronized blocks using boxed primitives. Find them now. The official JEP 401 specification outlines the migration plan in detail.

Key Takeaways

  • Project Valhalla’s JEP 401 merged today into JDK 28 — the biggest Java memory model change in a decade, after 12 years of development
  • Value classes eliminate object identity, enabling scalarization (fields in registers, no heap allocation) and heap flattening (dense array storage, ~3x speedup)
  • Records and value classes are orthogonal: value record Point(int x, int y) {} combines both for maximum benefit
  • Generic collections still box value objects — List<Point> performance won’t improve until specialized generics arrive in a future JEP
  • Production code synchronizing on Integer, Long, or other value-based types will break when they migrate — audit now during the JDK 28 preview window
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 *

    More in:News