Project Valhalla Explained: How a Decade of Work Arrives in JDK 28
project valhallajdk 28jep 401openjdkjavajava performancevalue classesjvmprogrammingsoftware developmentcache localityvector api

Project Valhalla Explained: How a Decade of Work Arrives in JDK 28

We've been hearing about Project Valhalla since 2014. A decade. Ten years of "it's coming," "it's almost here," "this will fix Java." Now, in June 2026, we're finally getting a preview feature in JDK 28, expected March 2027. The sentiment is mixed: excitement that it's "happening," but also frustration that after all this time, what's landing is just the first step, with critical parts of the original vision still missing. The biggest complaint? "They didn't ship the most important part." And honestly, it's a valid point.

The core problem Project Valhalla set out to fix is fundamental to Java's performance ceiling, particularly in data-intensive applications. Every non-primitive type in Java, even a simple Integer holding the value 5, has a unique identity in memory. It's an object, a reference. This architectural choice, while foundational to Java's object-oriented paradigm, means that when you have an array of Integer objects, you don't have a contiguous block of numbers. Instead, you have an array of pointers to numbers scattered across the heap, leading to significant memory overhead and performance penalties.

This constant dereferencing is a major culprit in killing cache locality, a death by a thousand paper cuts for data-intensive applications. Modern CPUs thrive on predictable, contiguous memory access. When processing vast amounts of data—like pixels (RGBA), audio samples (FL C FR SL SR SW), or RF samples (I Q) at millions of samples per second—the CPU is constantly chasing pointers, leading to frequent cache misses and stalled pipelines.

This inefficiency forces developers to implement hideous, hard-to-maintain workarounds, often pushing them towards C++ for performance-critical sections. Indeed, I've witnessed entire teams rewrite core logic in JNI just to circumvent this exact problem, a testament to the severity of the issue Project Valhalla aims to resolve.

Project Valhalla: The First Step with JEP 401 and Value Classes

JEP 401, officially titled "Value Classes and Objects," marks the first concrete delivery of Project Valhalla's vision. This isn't a minor update; it represents a massive change, encompassing over 197,000 lines of code across 1,816 files, targeting integration into the OpenJDK mainline by early July 2026 for JDK 28. It's a deep rewrite of how the Java Virtual Machine fundamentally thinks about object identity, moving towards a more efficient data model. For more technical details, you can refer to the official JEP 401 documentation.

The core idea behind value classes is deceptively simple yet profoundly impactful: introduce types that lack identity. Unlike traditional Java objects, value objects are distinguished solely by the values of their fields. If two value objects possess identical field values, they are considered equal, regardless of their memory location. This fundamental shift allows the JVM to perform significant optimizations in storage and memory layout. Instead of an array of references pointing to scattered objects, you get an array of actual data, laid out contiguously in memory, much like primitive arrays.

Project Valhalla contiguous memory for performance

This is the essence of the "looks like a class, codes like an int" mantra that has been central to Project Valhalla's philosophy. For developers, it means the == operator for value types will behave like primitive equality, comparing values directly rather than memory references. This paradigm shift is crucial for dramatically improving cache locality and iteration performance. The days of constantly chasing pointers for every element in a data structure, leading to performance bottlenecks, are intended to become a relic of the past.

This initial JEP will lay the groundwork for migrating existing JDK classes, such as Integer, to value classes, promising future performance gains for fundamental types. However, here's the kicker, and where much of the developer frustration stems from: this is strictly a preview feature. Developers must explicitly opt-in to use it, signaling its experimental nature. More importantly, and perhaps most controversially, value objects introduced in JDK 28 can still be null. This compromises the full "primitive-like" behavior many expected from Project Valhalla.

The Nullability Hangover and Missing Pieces in Project Valhalla

The original, more ambitious vision for Project Valhalla included concepts like "primitive classes" with dual projections and full null-safety. The fundamental idea was that value objects would be non-nullable by default, truly behaving like primitives in every respect. However, this comprehensive vision is not what's landing in JDK 28.

The crucial fact that value objects can still be null in this first preview means we're not yet realizing the full benefits of primitive-like behavior. It's a pragmatic compromise, a necessary cut to get something out the door, but it undeniably leaves a significant portion of Valhalla's potential on the table, particularly regarding type safety and performance guarantees.

This also means that the full value semantics, encompassing the complete relinquishment of nullability and robust "atomicity-safety-under-race" guarantees, remain future work for Project Valhalla. Developers should be prepared for deliberate breaking changes down the line as the project matures. A prime example: once Integer fully transitions to a value class, the long-standing practice of synchronizing on Integer objects will fundamentally fail. This represents a critical P0 issue waiting to happen for any legacy system relying on such behavior. The last time I encountered a pattern this fragile, it led to a 3 AM P0 incident, debugging a race condition in a deeply embedded legacy system.

The highly anticipated Vector API, designed to bring Single Instruction, Multiple Data (SIMD) operations to Java with its Vector<> type, is another critical feature currently waiting on Project Valhalla. Its performance, which relies heavily on contiguous data, would be severely impacted by the constant dereferencing inherent in traditional Java objects. Consequently, the Vector API cannot exit its own preview status until Valhalla itself moves beyond preview. Thus, this first step in Valhalla, while significant in its own right, is essentially unlocking the next major bottleneck for other crucial performance-enhancing APIs.

Project Valhalla data flow through CPU with contiguous memory access

The Road Ahead for Project Valhalla: Manage Your Expectations

So, what does this initial rollout of Project Valhalla mean for Java engineers in practice? JDK 28, with its expected release in March 2027, will offer a crucial first taste. Developers will gain the ability to declare their own custom value classes for pure data types—think coordinates, currency amounts, or complex numbers—benefiting from the new memory layout. Additionally, you'll observe some internal JDK classes beginning to leverage these new value semantics. However, it's vital to temper expectations: do not anticipate a magic bullet that instantly resolves all your performance woes across the board.

This is unequivocally an incremental rollout, a testament to the sheer complexity of fundamentally altering Java's object model. JEP 401, while monumental, is indeed "just the first part." The full, ambitious vision of Project Valhalla—where value objects are truly primitive-like, non-nullable by default, and offer comprehensive atomicity guarantees—is still years away from complete realization. We are realistically looking at JDK 29 (expected September 2027) and subsequent releases for further previews, refinements, and eventual finalization of the complete Valhalla feature set.

My take on Project Valhalla's current status? It's a necessary, long-overdue step that addresses a core limitation of Java. The engineering effort involved in rewriting 197,000 lines of code and fundamentally changing the JVM's object model is nothing short of immense.

However, this incremental approach, while pragmatic for such a massive undertaking, places a clear onus on developers to manage their expectations carefully. Do not jump into JDK 28 expecting a complete, instantaneous shift in Java's performance landscape. Understand that it's a preview, be aware of its current limitations (especially nullability), and prepare for more breaking changes and evolutions as the project matures. The full "looks like a class, codes like an int" dream, while closer, is still partially deferred.

Alex Chen
Alex Chen
A battle-hardened engineer who prioritizes stability over features. Writes detailed, code-heavy deep dives.