the problem with it is entirely cultural. why is `IStatusChangeEntityCreationManagerFactory` everywhere?
and why are the frameworks so huge and all encompassing? i think batteries included rails-style frameworks are great, but when i wrote Java, it didn't feel like rails at all
I know and like Java for almost 30 years now. It is amazing how carefully the language is beeing refined. For the cultural aspect, yes, that is sadly true, but I have the feeling that the culture changes. More and more developers realize that there is a better way now (e. g. records instead of dumb classes full of getters and setters). Maybe the main problem is bloated frameworks and their stickyness. The Helidon framework, for example, is a breath of fresh air compared to Spring. Go developers complaining about huge Java frameworks and boilplate could be happy with it.
Today it is a great language with a runtime that is unequaled. For heavy duty business backend server load, it is the standard choice, and rightfully so.
Do I love Spring? No. Do I prefer Typescript for my little side projects? Yes.
I'm always amazed by how much thinking and work the Java leads put in rolling out changes that move the language forward, but make it backward compatible as much as possible.
Java is to JavaScript what a Car is to Carpet. Very different beasts, though a lot V8 work was inspired by Hotspot that's just because of common VM patterns not the syntax of the languages.
I've been annoyed too by the lack of Temporal support in Safari. It's supposedly behind a --useTemporal flag, but I've never been able to get flags to work even when launching the binary directly, and I can't find anything in developer options or feature flags settings either so like. Does it even exist at all??
Java has a mechanism for Integer and Long objects caching using something that already looks like value object, cached objects can be compared using ==. hashCode of Integer already returns int, the boxed int value. Not much of value is lost.
That is a nice piece piece of knowledge! We have an Integer cache in our product, and the only reason that it hangs around is that it caches 0..1024 instead of -127..128. By setting this value, we could simplify our code, ever so slightly.
Any project depending on Integer identity had years of warning that this change would come. Also given implicit primitive conversions and object pooling Integer isn't exaclty a prime candidate for object identity to begin with.
As far as I understood this (plus future work) will make value classes work more like structs meaning it will save memory and align memory better for things like gRPC, etc.
Unless CPU instructions become widespread that allow to process 128 bits in one step, then yes. Java will have the same limitations as any other language. Other languages simply don't make this explicit.
IIUC value objects can have any size, it's just that 'reference flattening' requires the object to fit into a machine word. But this is only due to how Java represents object references and its atomicity guarantees.
Naturally, a language that properly supports value semantics does not have any of these limitations.
I don’t understand this comment - the .NET CLR supports arbitrarily large value types. Are you referring to something like “atomic flattening of those types” instead? Because the CLR doesn’t guarantee that, and therefore supports flattening.
Basically JEP401 guarantees that just adding "value" to the class won't change behaviour, which also means that you are not allowed to see object tearing, which requires atomic operations on the field.
Relaxing that would break safe publication rules, at least for Java.
Not for atomic writes, which is the important bit here. When dealing with concurrency the choice to make us will you allow tears when writing i.e. thread A writes aa and thread B writes bb. Will you allow the option of seeing ab or ba or only aa/bb. This is the thing that costs performance. Plus do you allow null which makes it harder too.
You can recover the history using their tooling build on top of their bugtracker and GitHub. Specifically they capture the discussions and all small changes over time in their skara tools and are prepared to leave GitHub if needed. They had multi de adres experience and had multiple prior code repos. Still do if i understand as the Oracle team has the sun and bea code repositories pre openjdk preserved.
Seems like a horrible way to work. Why could this not have landed as a large amount of smaller PRs in a more incremental fashion, maybe Java users could have gotten some value out of it earlier.
Out of all factors this certainly isn't it. If anything, more projects could learn from the way Valhalla was handled.
It started out as a highly invasive, highly disruptive and highly experimental branch that eventually turned into a beautiful specification that put semantics and performance payoff first and syntax seconds.
I think it is important to understand what this does and does not cover. This is “only the first part of Valhalla”. See e.g. a good summary at https://www.jvm-weekly.com/p/project-valhalla-explained-how-...
I feel lonely in that: I mostly love Java as a language.
The lack of value types is the biggest impediment to certain types of performance. I am really looking forward to this evolution of the language.
java the language is amazing
the problem with it is entirely cultural. why is `IStatusChangeEntityCreationManagerFactory` everywhere?
and why are the frameworks so huge and all encompassing? i think batteries included rails-style frameworks are great, but when i wrote Java, it didn't feel like rails at all
none of these are language problems
I know and like Java for almost 30 years now. It is amazing how carefully the language is beeing refined. For the cultural aspect, yes, that is sadly true, but I have the feeling that the culture changes. More and more developers realize that there is a better way now (e. g. records instead of dumb classes full of getters and setters). Maybe the main problem is bloated frameworks and their stickyness. The Helidon framework, for example, is a breath of fresh air compared to Spring. Go developers complaining about huge Java frameworks and boilplate could be happy with it.
Today it is a great language with a runtime that is unequaled. For heavy duty business backend server load, it is the standard choice, and rightfully so.
Do I love Spring? No. Do I prefer Typescript for my little side projects? Yes.
I'm always amazed by how much thinking and work the Java leads put in rolling out changes that move the language forward, but make it backward compatible as much as possible.
It's pretty interesting that while both languages still receive new features, Java seems to stay ahead of JavaScript:
- Java has long had a modern replacement for Date, while JavaScript's recently standardized Temporal API still isn't supported in Safari.
- Java has switch expressions, while JavaScript, despite its Scheme influence, does not.
- And now Java is getting value objects, while JavaScript's equivalent tuples & records proposal has been withdrawn.[0]
JavaScript was not developed as a fork of Java, but much of its basic syntax still resembles Java, so I think it's fair to compare them.
[0]: https://github.com/tc39/proposal-record-tuple
I personally would never compare the two. Someone said: java to JavaScript is like car to carpet. And I completely agree with that.
Java is to JavaScript what a Car is to Carpet. Very different beasts, though a lot V8 work was inspired by Hotspot that's just because of common VM patterns not the syntax of the languages.
I've been annoyed too by the lack of Temporal support in Safari. It's supposedly behind a --useTemporal flag, but I've never been able to get flags to work even when launching the binary directly, and I can't find anything in developer options or feature flags settings either so like. Does it even exist at all??
It is enabled by default in STP, so presumably it will launch alongside the 27 releases.
Note Temporal was in the Ecmascript 2026 release back in March.
If I understand this correctly then Integer becomes a value class and every instance of it loses its object identity.
I do not have a lot of knowledge about the details but from the outset it seems like a rather bold move to me.
Java has a mechanism for Integer and Long objects caching using something that already looks like value object, cached objects can be compared using ==. hashCode of Integer already returns int, the boxed int value. Not much of value is lost.
Of particular note, all 1-byte Integers are interned, there is a pool of small Integers from -127 <-> 127 which are reused whenever possible.
I learned this the hard way, when a C++ JNI extension I was working on accidentally overwrote the pooled value for zero, and all hell broke loose...
> Integers from -127 <-> 127
The cache can be extended on startup with env var `java.lang.Integer.IntegerCache.high `
https://github.com/openjdk/jdk/blob/cc278dbb8a1ca0754d584270...
That is a nice piece piece of knowledge! We have an Integer cache in our product, and the only reason that it hangs around is that it caches 0..1024 instead of -127..128. By setting this value, we could simplify our code, ever so slightly.
Any project depending on Integer identity had years of warning that this change would come. Also given implicit primitive conversions and object pooling Integer isn't exaclty a prime candidate for object identity to begin with.
As far as I understood this (plus future work) will make value classes work more like structs meaning it will save memory and align memory better for things like gRPC, etc.
It's really nice to see movement here finally. Lack of value types has been one of the biggest performance pitfalls in Java for decades at this point
Really cool, shame that strings can’t be fully indistinguishable like Integer despite their immutability
Is there a theoretical reason why they can’t?
As a layman I would assume nothing is preventing it, other than the large amount of effort it would take to implement.
No theoretical reason; It's backward compatibility/internal technicalities, as they mention in the JEP.
What's the latest status? Is it still limited to 63-bits of data plus 1 bit for nullability?
Unless CPU instructions become widespread that allow to process 128 bits in one step, then yes. Java will have the same limitations as any other language. Other languages simply don't make this explicit.
IIUC value objects can have any size, it's just that 'reference flattening' requires the object to fit into a machine word. But this is only due to how Java represents object references and its atomicity guarantees.
Naturally, a language that properly supports value semantics does not have any of these limitations.
I don’t understand this comment - the .NET CLR supports arbitrarily large value types. Are you referring to something like “atomic flattening of those types” instead? Because the CLR doesn’t guarantee that, and therefore supports flattening.
That is exact problem.
Basically JEP401 guarantees that just adding "value" to the class won't change behaviour, which also means that you are not allowed to see object tearing, which requires atomic operations on the field.
Relaxing that would break safe publication rules, at least for Java.
We've had MMX for a while now, I don't think we need to wait much longer.
I don't really see why you would need specific hardware to express a type in a programming language, though.
Not for atomic writes, which is the important bit here. When dealing with concurrency the choice to make us will you allow tears when writing i.e. thread A writes aa and thread B writes bb. Will you allow the option of seeing ab or ba or only aa/bb. This is the thing that costs performance. Plus do you allow null which makes it harder too.
It's mostly a performance question in order to adhere to Java's memory model.
2934 commits OMG... huge work.
The way pull requests and commits work in the OpenJDK repository -- a bot squashes each pull request into one commit: https://github.com/openjdk/jdk/pull/31120#issuecomment-51378...
The final singular commit is cc278db (8389219: Implement JEP 401: Value Objects (Preview), 2026-07-31) https://github.com/openjdk/jdk/commit/cc278dbb8a1ca0754d5842...
Is there a writeup on why they choose to destroy the history?
You can recover the history using their tooling build on top of their bugtracker and GitHub. Specifically they capture the discussions and all small changes over time in their skara tools and are prepared to leave GitHub if needed. They had multi de adres experience and had multiple prior code repos. Still do if i understand as the Oracle team has the sun and bea code repositories pre openjdk preserved.
It's a project years in the making.
Yes, massive respect for that type of perseverance on long term, important changes.
Seems like a horrible way to work. Why could this not have landed as a large amount of smaller PRs in a more incremental fashion, maybe Java users could have gotten some value out of it earlier.
Out of all factors this certainly isn't it. If anything, more projects could learn from the way Valhalla was handled.
It started out as a highly invasive, highly disruptive and highly experimental branch that eventually turned into a beautiful specification that put semantics and performance payoff first and syntax seconds.
This is incremental. This change is the smallest possible one that could work. There are more coming in later.
The MR is closed
This is it https://github.com/openjdk/jdk/commit/cc278dbb8a1ca0754d5842...
https://github.com/openjdk/jdk/pull/31120#issuecomment-51378...
How much of Valhalla is this? 50% of it? 90% of it?
50% maybe.
There are other projects that depend having it in place, SIMD (vectors), reiffed generics, non nullable types.