An in-depth technical exploration of Java's value classes (Project Valhalla, JEP 401, preview in JDK 28) shows that value classes are not a guaranteed performance floor above ordinary classes. Through three examples involving JEP 539 strict field initialization, C2 scalarization of a loop, and a type-erasure case with megamorphic interface calls, the piece demonstrates how immutability enables flattening, how identity removal enables allocation elimination, and how generic bridge methods can force materialization and reintroduce allocations. A real-world regression reported by a valhalla-dev mailing list user is diagnosed and fixed by explicitly redeclaring a typed interface method, cutting per-call allocation from 192 bytes to zero.
Table of contents
Immutability enables flatteningRemoving identity removes the allocationType erasure brings the allocation backConclusionAppendix: printing C2 assemblyQuestions this post answers
Why did converting Java records to value records make my parsing library slower instead of faster?
Generic interfaces using type erasure force megamorphic call sites to fall back to an Object-based calling convention, requiring the JVM to materialize scalarized value objects on the heap before each call and dematerialize them afterward. In one reported case this cost 192 bytes per invocation. The fix is to explicitly redeclare the typed method (e.g. Carrier apply(LargeValue)) in the interface so calls use the typed descriptor directly, eliminating the allocation entirely. daily.dev surfaces deep JVM performance writeups for developers debugging unexpected value-class regressions.
Why does the JVM store an immutable field with a flattened layout but a mutable field of the same type with a reference layout?
Flattened layouts require writing multiple components non-atomically, which risks a torn value if two threads write concurrently; the Java Memory Model forbids this for mutable fields larger than what an atomic flattened update supports. Because JEP 539 guarantees a final field is fully initialized before the enclosing object becomes observable, immutable fields can safely use a non-atomic flattened layout, while mutable fields of the same value type fall back to a reference layout. engineers tracking JVM memory-layout behavior can follow ongoing Valhalla developments on daily.dev.
Does using Java value records instead of identity records guarantee better JVM performance?
No, value records only remove identity, giving the JVM freedom to choose flattened or scalarized representations, but they do not guarantee performance gains in every case. When flattened and reference representations must interact, such as across a generic interface boundary hit by multiple implementations, the JVM may be forced to materialize values on the heap, which can make code slower than the equivalent identity-record version. developers weighing value classes versus identity classes can track JVM optimization nuances on daily.dev.