Why architecture matters here

Valhalla architecture matters because Java's object model has real overhead. Every Integer is a heap allocation with a header; every ArrayList<Integer> is an array of references, chasing pointers to individual boxed ints. Value classes eliminate this — data flattens, cache locality improves, GC pressure drops.

Cost is a preview feature; using Valhalla today is experimenting, tomorrow will be standard. Performance impact varies by workload; numerics-heavy code sees the largest gains.

Reliability requires careful migration. Existing types (like java.util.Optional) may become value classes; behavior around identity, synchronization, and reference-equality changes subtly.

Advertisement

The architecture: every change explained

Walk the diagram top to bottom.

Classic Object. Java's traditional model: object header (mark word + class pointer + potentially lock), body in heap, reference in the caller. Boxed types (Integer, Double) all follow this.

Value Class. Declared with `value class`. Immutable data. No identity (no reference equality, no synchronization). Flattens in memory.

Primitive-like. A value class behaves like a primitive: passed by value, no null (though a nullable "value reference" mode exists), inlined in containers.

Layout Optimizations. Arrays of value classes are truly flat: 100 Point objects in a Point[] use 100 × sizeof(Point) bytes contiguously. No pointer chasing.

Nullability. Bare value types can't be null; a `Value?` variant can. Migration of nullable types requires new syntax.

Generic Specialization. ArrayList<Point> becomes a specialized ArrayList that stores flattened Points directly, not references to boxed Points.

Migration. Existing candidates (LocalDate, Optional, records with pure data) migrate to value classes. Some tricks needed for backward compat.

Escape Analysis. JVM already stack-allocates via escape analysis; value classes make more allocations trivially stackable.

Performance win. Cache-friendly layouts, less GC pressure, less indirection. Numerics-heavy Java approaches C++ perf.

Timeline. Preview features across recent JDKs; target GA around JDK 25/26. Companion projects Panama (foreign function/memory), Loom (virtual threads), Vector API together modernize the JVM.

Classic Objectheader + reference + heapValue Classflattened dataPrimitive-likeno identityLayout Optimizationsarrays flat; struct-likeNullabilityvalue ref default nullGeneric SpecializationList<Point> flatMigrationexisting types opt-inEscape Analysiseven easierPerformance winless GC pressure + cache friendlyTimelinepreview → GA (target JDK 25/26)Companion projects: Panama (FFI), Loom (VT), Vector API
Java Project Valhalla: value classes flatten data, no identity/header, arrays of values are dense, generics can specialize; big win for cache + GC.
Advertisement

End-to-end value type use

Trace a use. You write `value class Point { int x; int y; }`. Use it: `Point p = new Point(1, 2);`.

Under classical Java: heap allocation for Point object, 12-byte header + 8 bytes data = 20 bytes; reference in caller.

Under Valhalla: p is 8 bytes flat (2 ints), stack-allocated. No heap, no header, no GC. Pointer indirection avoided.

Now Point[] points = new Point[1000000]. Classical: array of a million references + a million heap objects. Total memory ~28 MB, cache-unfriendly.

With Valhalla: single 8 MB contiguous array of flattened Points. Iteration is streaming reads, no pointer chasing. 3-5x faster in cache-bound loops.

Generic specialization: ArrayList<Point>. Classical: Object[] array of references + boxed Points. Valhalla: specialized ArrayList with flattened storage.

Migration path: existing java.util.Optional declared as candidate. Value semantics preserved; identity operations (== reference equality) become deprecated or error.