Picture two identical twins. They look the same, they answer to the same questions the same way — but they are still two different people. If you ask "are these the same person?", the honest answer is no, even though they're indistinguishable in every way that matters to you.
That's exactly the trap Java has set for developers since its very first version. And a project called Valhalla — yes, named after the Norse warriors' afterlife, because it has taken that long to get here — is the JDK team's attempt to finally close it.
The bug hiding in plain sight
In Java, almost everything you create — a date, a number wrapped in an object, a custom class — is what's called a reference type. When you create one, Java doesn't just remember the value you gave it. It also stamps it with an invisible identity, like a serial number, and stores it at its own address in memory.
So if you create two dates that both represent June 21, 2026, and ask Java "are these two the same?", using the most natural comparison (==), Java says no. Not because the dates are different — they're identical — but because they're two separate "twins" sitting at two separate addresses.
It gets weirder with plain numbers
Here's the part that trips up even experienced developers. Java's Integer — the object version of a whole number — secretly caches small values. Numbers below 128 get reused from a shared pool, so two small Integer objects with the same value can pass the == check. But the moment the number is 128 or higher, that caching stops, and the same check silently starts failing.
Same code. Same logic. Different answer, purely because of which number you picked. Most Java linters now warn developers never to use == on Integer for exactly this reason — it's a trap that depends on an implementation detail nobody should have to remember.
The fix: a class that gives up its "identity"
JEP 401 — short for JDK Enhancement Proposal 401, the official Valhalla proposal — introduces a new kind of class called a value class. Instances of a value class don't have that invisible serial number at all. Two value objects holding the same data are the same, by definition, because there's nothing left to distinguish them other than their values.
The JDK team plans to gradually migrate existing classes like Integer to this new model, and developers will be able to write their own value classes too.
value: 200
value: 200
Why the JDK team cares about more than fixing a bug
If this were only about fixing a confusing comparison, it might not be worth 12 years of engineering effort. The real prize is performance. Reference types always need an extra hop — go to the variable, follow it to an address, then read the value sitting there. Value types remove that hop entirely, since the value can sit directly where it's used.
For a single number, that hop costs you nothing you'd notice. But software rarely deals with a single number — it deals with millions of them, in loops, in lists, in financial calculations running thousands of times a second. Removing one unnecessary hop, repeated a million times, becomes a measurable speed difference. That's the actual bet Project Valhalla is making.
synchronize on an Integer will start throwing an exception, since value objects have no monitor to lock on. Goetz himself doesn't expect JEP 401 to exit preview before JDK 29, the next LTS — so production teams have a long runway to plan the migration, not a deadline to scramble for.
Where this lands in the release calendar
Valhalla Began
First Preview PR
for JEP 401
Why this matters even if you never touch Valhalla code
Most developers will never write a value class by hand in the next two years. But every Java application — including the loan-processing pipelines and KYC microservices I build day to day — ultimately runs on the assumptions the JVM makes about memory and objects. When the platform gets cheaper at the lowest level, every layer built on top inherits some of that headroom, whether or not the team writing the business logic ever thinks about it.
== confusion.