After 12 years of development, Project Valhalla is finally landing as a preview feature in JDK 28. The implementation required 197,000 lines of code changes across the JDK codebase, making it one of the largest engineering efforts in Java’s history. Brian Goetz, Java language architect at Oracle, has publicly warned developers that the feature will likely remain in preview even through the next LTS release.
TL;DR: Project Valhalla arrives as a preview feature in JDK 28 after 12 years of development, delivering value classes through JEP 401. The implementation required 197,000 lines of code across the JDK codebase, with benchmarks showing up to 3x performance improvement from memory flattening.
What Is Project Valhalla and Why Did It Take 12 Years?
Project Valhalla is a massive initiative to bring value types to the Java platform, and it has been in active development since 2014. The effort encompasses roughly 197,000 lines of code modifications spread across the entire JDK codebase. According to JVM Weekly, the situation around the release is nuanced — the feature is landing as a preview, not a finished product. That distinction matters enormously for enterprise teams.
So why did this take over a decade? The answer lies in how deeply the change cuts. Java’s entire memory model, garbage collector interactions, and bytecode specification were built around the assumption that every object is a heap-allocated entity with identity. Value classes break that fundamental assumption by introducing identity-free objects that can live directly on the stack or inline within other objects. Every JVM component had to be re-examined.
Brian Goetz, who has led the project since its inception, warned developers at The Register that Valhalla will likely still be in preview status during the next LTS release. The team is prioritizing correctness over speed. Rushing a change this deep into the JVM’s architecture could destabilize millions of production systems worldwide.
The scope here is staggering. Think about that for a moment.
How Do Value Classes Differ from Regular Java Objects?
Regular Java objects carry object identity — a hidden header containing a monitor, hash code, and GC metadata — which adds roughly 16 bytes of overhead per instance on 64-bit JVMs. Value classes eliminate this header entirely. They are immutable by default and cannot use synchronization primitives like synchronized or wait. This trade-off is intentional: sacrificing identity unlocks density.
Here is a concrete comparison of how the two models behave:
| Characteristic | Regular Object | Value Class |
|---|---|---|
| Identity | Yes (hidden header) | No header, no identity |
| Allocation | Always heap | Stack or flattened inline |
| Mutability | Mutable by default | Immutable |
| Synchronization | synchronized allowed | Not permitted |
| Nullability | Nullable | Non-null by default |
| Memory overhead | ~16 bytes header | Zero header bytes |
| Default value | null | Type-specific zero value |
| Equality | Reference identity | Structural (field-by-field) |
A value class declared with the value keyword compiles to a new bytecode category that the JVM treats differently during allocation. When you create an array of value class instances, the JVM lays them out contiguously in memory rather than storing references to scattered heap objects. This eliminates pointer chasing entirely.
The implications for cache locality are profound. Modern CPUs spend significant cycles waiting for memory fetches. Contiguous arrays mean fewer cache misses. The CPU prefetcher works efficiently when data lives in adjacent addresses. For numerical computing and data-heavy applications, this single architectural difference can transform throughput characteristics.
What Performance Gains Does JEP 401 Deliver?
Benchmarks from the Valhalla development team show up to 3x performance improvement for workloads dominated by small, short-lived objects. The gains come primarily from eliminating allocation pressure on the garbage collector. When value class instances live on the stack instead of the heap, the GC never sees them. They simply vanish when the stack frame pops. No finalization, no tracing, no overhead.
The performance improvements scale with allocation rate. Applications that create millions of small objects per second — financial tick data, physics simulations, game entity components — benefit most. According to analysis from dasroot.net, the flattening effect also reduces memory footprint by removing the per-object header. A Point class with two int fields drops from 24 bytes (16-byte header plus two 4-byte fields) to just 8 bytes. That is a 66% reduction in memory per instance.
Here is where the numbers get interesting for enterprise teams. Consider a system processing market data at scale. A single PriceTick value class replacing a traditional object would save 16 bytes per tick. At one million ticks per second, that translates to roughly 16 MB of allocation pressure eliminated every second. The garbage collector stops scanning objects that do not exist on the heap.
These are not theoretical micro-benchmark gains. The 3x figure represents real workload patterns where allocation dominates execution time. However, Goetz has cautioned that not every application will see dramatic improvements. Code that relies heavily on identity-based semantics — inheritance hierarchies, framework-heavy DI containers — may need refactoring before value classes provide measurable benefits.
How Does Memory Flattening Work Under the Hood?
Memory flattening is the core mechanism that makes value classes fast. When the JVM encounters a value class field inside another object, it does not insert a reference pointer. Instead, it copies the value class’s fields directly into the containing object’s memory layout. The same principle applies to arrays. An array of value class instances stores the raw field data in consecutive memory addresses, with no pointer indirection between elements.
The JVM achieves this through a new memory layout strategy during class loading. When the class loader processes a value class definition, it records the flattened size and alignment requirements. For nested value classes — a value class containing another value class — the JVM recursively flattens the inner fields into the outer layout. This produces a single contiguous block of memory regardless of nesting depth.
The bytecode layer required corresponding changes. JEP 401 introduces new opcodes and modifies the verification rules to distinguish between reference types and value types. The verifier must ensure that value class instances are never treated as identity-bearing objects — attempting to synchronize on a value class instance triggers a verification error at class load time. This strict enforcement happens early, preventing subtle runtime failures.
The compilation pipeline also changed. The JIT compilers (C1 and C2 in HotSpot) received updates to recognize value class patterns and apply scalar replacement more aggressively. Escape analysis, which determines whether an object can safely live on the stack, becomes significantly more effective when the object has no identity to preserve. The compiler can decompose a value class instance into its constituent fields and keep each field in a CPU register. No memory allocation at all.
Which JDK 28 Features Are Included in the Valhalla Preview?
JDK 28 delivers the first functional preview of value classes through JEP 401, representing 197,000 lines of code developed over 12 years since the project’s inception in 2014. The preview introduces value classes as a core language feature, enabling developers to define types that are immutable, identity-free, and optimized for flat memory layout. According to coverage from JVM Weekly volume 180, the situation remains nuanced — this is a preview, not a final specification.
The preview includes several concrete capabilities that developers can immediately experiment with. The feature set focuses on giving JVM engineers and library authors the tools to measure real-world performance gains before stabilization. Performance benchmarks referenced in ecosystem coverage show potential speedups of up to 3x for certain workloads. That is a significant jump.
Specific capabilities in the JDK 28 preview include:
- Value class declaration syntax using the
valuekeyword modifier on class definitions, allowing developers to mark classes as identity-free - Flat memory layout where value class instances are stored inline in their containing object or array rather than as heap-allocated references
- Immutability enforcement requiring all fields to be final, preventing modification after construction
- Null-free type semantics for value class instances, eliminating the overhead of null checks at runtime
- Acyclic initialization rules preventing value classes from containing references to themselves during construction
- Array flattening optimization where arrays of value class instances are stored contiguously rather than as arrays of pointers
- Restricted constructor patterns that ensure consistent and predictable initialization behavior
- Interoperability with existing reference types allowing value classes and traditional reference classes to coexist in the same codebase
The Register reports that architect Brian Goetz has explicitly warned developers about expectations. This is experimental territory.
| Feature | Included in JDK 28 Preview | Status |
|---|---|---|
| Value class declarations | Yes | Preview |
| Flat memory layout | Yes | Preview |
| Immutability enforcement | Yes | Preview |
| Specialized generics | No | Future JEP |
T.default literals | Partial | Under review |
| Null-suppression markers | Partial | Under review |
As dasroot.net’s technical analysis explains, the memory flattening behavior is the most architecturally significant piece. When a value class instance is embedded inside another object, the JVM eliminates the pointer indirection entirely. Fields are laid out directly in the containing object’s memory space.
Will Valhalla Be Stable in the Next LTS Release?
No. According to The Register’s June 15, 2026 report, Java architect Brian Goetz has explicitly warned developers that Valhalla will likely still be in preview status during the next LTS release cycle. The feature requires extensive real-world testing before the OpenJDK team commits to a stable specification. Developers should not build production systems assuming final semantics.
The hesitation stems from the sheer complexity of the change. Project Valhalla touches the deepest layers of the JVM, the Java Language Specification, and the bytecode format. Getting any of these wrong could create compatibility problems that persist for decades. The OpenJDK team has spent 12 years on this work.
JVM Weekly’s coverage notes that the situation is “a bit nuanced” — the preview exists, but stabilization requires feedback from library maintainers, framework authors, and large-scale enterprise deployments. The 197,000 lines of code represent implementation effort, not finalization. Goetz and his team need production-like workloads to surface edge cases.
This means teams evaluating Valhalla today should treat the API and semantics as subject to change. Breaking changes between preview releases are expected and documented. The next LTS will likely ship with Valhalla still behind a preview flag.
How Does Valhalla Affect Existing Java Codebases?
Existing Java code continues to run without modification on JDK 28, as value classes are an additive feature that does not break backward compatibility. However, the introduction of identity-free types creates new considerations for libraries that rely heavily on object identity, synchronization, or reference semantics. Code that uses == for identity comparison or calls Object.wait() and notify() will need careful auditing.
The migration story is gradual. Developers can adopt value classes in new code without touching existing reference-based classes. The JVM handles both uniformly at the bytecode level, though value class instances bypass the standard object header and identity hash mechanisms. This is where the performance gains originate.
From a practical standpoint, the most immediate impact falls on library and framework authors rather than application developers. Collections frameworks, serialization libraries, and ORM tools will need updates to handle value types correctly. Performance-sensitive libraries that currently use primitive arrays or Unsafe operations may find value classes offer a safer, more maintainable alternative.
Dasroot.net’s analysis highlights that enterprise teams should begin auditing their code for patterns that assume object identity. The transition will be measured in years, not months.
What Are the Limitations of the Current Preview?
The JDK 28 preview of Project Valhalla carries several documented limitations that restrict its use in production environments. Value classes cannot participate in certain operations that depend on object identity, including synchronization, weak references, and identity-based equality checks. The feature also requires explicit preview flags during compilation and runtime.
Key limitations include:
- No synchronization support — value class instances cannot be used with
synchronizedblocks since they lack monitor locks - No subclassing — value classes are implicitly final and cannot be extended by other classes
- Restricted use in reflection APIs — some reflective operations behave differently or throw exceptions when targeting value class instances
- Preview-only status — code using value classes requires
--enable-previewflags at both compile time and runtime - No specialized generics yet — the current preview does not include the specialized generics feature that would allow generic types to specialize on value type parameters
- Limited tooling support — IDEs, debuggers, and profilers may not fully understand value class semantics in the initial preview
- Serialization incompatibilities — existing serialization frameworks like Java’s built-in
Serializableinterface do not yet handle value classes correctly - Native interop constraints — JNI and foreign function interfaces may require updates to properly marshal value class instances
The absence of specialized generics is particularly notable. Many developers consider parametric polymorphism over value types to be the feature that unlocks the most performance. That work is scheduled for future JEPs.
How Does Valhalla Compare to Value Types in Other Languages?
Java’s value classes arrive more than a decade after similar features appeared in languages like C# and Kotlin, but the JVM’s design constraints make Valhalla’s approach architecturally distinct. C# introduced value types with its initial release through structs, which are stack-allocated and copied by value. Kotlin’s value classes (formerly inline classes) wrap a single underlying value and optimize away boxing in many cases.
Java’s approach differs because it must maintain backward compatibility with 28 years of existing bytecode and library code. The JVM Weekly analysis emphasizes that Valhalla’s design prioritizes migration safety over raw feature parity. Value classes in Java are heap-allocated when stored in fields of reference type, but flattened when stored in arrays or as fields of other value classes.
This hybrid model means Java developers get memory layout optimizations without sacrificing the platform’s runtime guarantees. The tradeoff is complexity in the specification and a longer stabilization period. Languages designed from scratch with value types do not face this constraint.
Frequently Asked Questions
Is Project Valhalla production-ready in JDK 28?
No. Project Valhalla ships as a preview feature in JDK 28 after 12 years of development encompassing 197,000 lines of code. Architect Brian Goetz has publicly warned that the feature will likely remain in preview status through the next LTS release, meaning production use is not recommended.
Can I migrate existing Java classes to value classes?
Migration is possible but requires careful refactoring, as value classes must be immutable, identity-free, and cannot use synchronization primitives. Classes that rely on Object.equals() identity semantics, mutable state, or synchronized blocks are not direct candidates. The preview allows new code to adopt value classes incrementally alongside existing reference types.
Will Valhalla be finalized before the next LTS release?
According to The Register’s reporting on June 15, 2026, Brian Goetz explicitly stated that Valhalla will “likely still be preview” in the next LTS release. The OpenJDK team needs feedback from real-world usage across the 197,000 lines of implementation before committing to a stable specification. Finalization is expected in a subsequent release cycle.
Do value classes break Java’s write-once-run-anywhere promise?
No. Value classes compile to standard JVM bytecode that runs on any compliant JDK 28 or later runtime. The memory layout optimizations are implementation details handled by the JVM, not exposed in the class file format in a way that breaks portability. Existing bytecode continues to run unchanged alongside value class code.
Summary
Project Valhalla’s arrival in JDK 28 as a preview feature marks the most significant change to Java’s type system in a decade. Here are the key takeaways:
- 12 years in the making — Project Valhalla began in 2014 and delivers 197,000 lines of code implementing value classes, flat memory layout, and identity-free semantics through JEP 401
- Preview only, not production — Brian Goetz has confirmed the feature will likely remain in preview through the next LTS release, requiring
--enable-previewflags and carrying breaking-change risk between updates - Up to 3x performance gains — benchmarks referenced in ecosystem coverage show significant speedups for memory-intensive workloads due to array flattening and eliminated pointer indirection
- Additive and backward-compatible — existing Java code runs unmodified on JDK 28, but libraries relying on object identity, synchronization, or reflection will need auditing before adopting value classes
- Specialized generics deferred — the current preview excludes parametric polymorphism over value types, a feature many developers consider critical for maximizing performance benefits
For developers working on performance-sensitive Java applications, now is the time to experiment with value classes in non-production environments. Read the full JEP 401 specification, test against your workloads, and provide feedback to the OpenJDK team. The stabilization timeline depends on community input from real-world usage.