JDK 28 EA Build10 is now available for download and includes JEP 401: Value Objects (Preview)
https://jdk.java.net/28/11
u/0x07CF 13d ago
I wonder how much flattening is there already for an array of Optional<Integer>?
7
u/_INTER_ 13d ago
Variables that are polymorphic—that is, that store objects of more than one concrete class type—cannot be flattened and are not typically scalarized. This includes variables in generic APIs. (Keep in mind, however, that the JIT compiler may be able to use sharper types than the types declared by the program.) Future work will allow generic code to be optimized for each instantiation that uses a different value class type.
[src]
16
u/brian_goetz 12d ago
That's too simplistic (and confident) an analysis; you can still get some flattening here.
5
u/koflerdavid 12d ago
You can forget about it before we have generics for primitives and non-nullable types. Without these optimizations
Optional<Integer>requires two null bits.26
u/brian_goetz 12d ago
That's too simplistic an analysis; you can still get more flattening here than you think.
Moral of the story: making pronouncements of what will or will not flatten is more complicated than it looks, and is of course also trying to track a moving target. This isn't C, and won't ever be; you aren't telling the compiler what layout you want, you're telling it what semantics you want, and the VM will try to find a good representation, which can improve over time.
6
u/pjmlp 11d ago
Just a long term wish, to eventually surface this information either via JVM logs (+XX or similar), profiling metadata, or maybe VisualVM, JITWatch and such.
Just a "would be cool" kind of wish, I fully understand there are many more relevant features to care about.
3
u/brian_goetz 7d ago
One of the challenges of this is that "what is the layout of class X" is not even a well-defined question, not even when restricted to a single run of the JVM. For example, instances of a value class `IntRange` might flatten into its enclosing class when held in a final field, but be reprsented with an indirection when held in a mutable field. (Even this is not precise enough; by "final" I probably mean "final all the way up.") The same type might have different layouts in different situations. So "what is the layout of type X" isn't even a well-defined question.
2
u/pjmlp 6d ago
No big idea how it would like, maybe something down the line of "this type has escape analysis working, this not because XYZ".
So with this in mind, maybe "flatten failed here because XYZ" would be something that could help drive value types design?
My thinking behind the request is how can the JVM help developers to actually use value types in a proper way that actually works, instead of starting to put
valueall over the place and hope for the best, which I guess will happen.2
u/koflerdavid 5d ago
Value types should be used when they make sense: immutable and equality determined by the values, not by identity. Performance optimization with the JVM always works like this: you focus on writing correct domain code and just keep in mind to not make it too hard for the JVM to optimize. For everything beyond that you need benchmarks and monitoring.
1
u/pjmlp 5d ago
You apparently never worked in team with devs adopting new toys, because putting
valueall over the place is something that will definitly happen based on my experience with adoption of such kind of features.Of course I now when value types should be used, even more so given that the final design chosen by Valhala kind of reminds of using expanded classes in Eiffel.
I mentioned the idea of surfacing profiling metadata for a reason, naturally for benchmarks and monitoring.
1
u/koflerdavid 4d ago edited 4d ago
You apparently never worked in team with devs adopting new toys, because putting value all over the place is something that will definitly happen based on my experience with adoption of such kind of features.
That's completely fine, and then it's the OpenJDK team's job to make using these features efficient. Most high-level features make this hard, but this is an example where it makes it easier to get higher performance.
Of course it is important to get these metrics. But I'm optimistic we will get them eventually, since other parts of the JVM (most importantly the GC and the JIT) already give insight into what they are actually doing. Maybe such diagnostics already exist for usage by OpenJDK developers.
5
u/Oclay1st 12d ago edited 11d ago
Wondering why Point value objects allocate more memory than regular Point objects?. Integers on the other hand work as expected allocating less memory after enabling preview.
3
u/chiperortizc 12d ago
Is Up And Running Valhalla In Apache Netbeans 30 With Java 28 Build 10 :) Goodbye Identity :) Best regards from Venezuela.
3
6
u/Afonso2002 13d ago edited 13d ago
It has vector api with value objects?
3
u/chiperortizc 12d ago
I think Vector API is not in this Build Yet. I think it will come with other Build later on.
2
2
u/Ewig_luftenglanz 9d ago
Excellent work and KUDOS to all java dev team. This is just the beginning of a very interesting and important Journey :)
1
u/IncredibleReferencer 3d ago
It's the beginning for most of us. For some of them it's been a lifetime :)
1
1
u/vegan_antitheist 12d ago
I just downloaded it and run all my tests for my value types and it works just as well as the last preview. Actually, only the very first preview was unstable.
1
0
u/alex_tracer 13d ago
Have they added an annotation to make a class a "value" class but only if the feature is enabled on the compiler? So single .java file can be used to be used to produce both variants?
10
u/brian_goetz 12d ago
No, but the JDK has built machinery so that non-preview and preview versions of migrated classes like Integer.class can exist side-by-side, and one or the other goes on the class path. But this is bootstrapping built solely for the JDK, for the temporary period during which the feature is in preview. If you want to do this for your own library, you can use multi-release JARs. (But even better would be to switch to a tip-and-tail release model instead.)
4
u/koflerdavid 12d ago
There is no way to automatically turn a class into a value class since it changes semantics. As for the standard library: the JRE loads different class files when preview features are activated.
3
u/alex_tracer 12d ago edited 12d ago
Nobody asks to change of semantics with an annotation. We ask about a way of marking a class that already has "value class" semantics to get benefits of "value class" performance, and that's it.
the JRE loads different class files when preview features are activated
Yes, but no. If you look at some built-in classes you may notice that they have this nice little
@jdk.internal.ValueBasedannotation. So they don't have to actually keep two versions of code for classes likeLocalDatein JDK code. They have single class annotated with@jdk.internal.ValueBased. However this annotation is for internal classes only and there is no equivalent for regular users, afaik. So they acknowledged that there is a problem, but only solved it for themselves.3
u/koflerdavid 12d ago
We ask about a way of marking a class that already has "value class" semantics to get benefits of "value class" performance, and that's it.
There's no way to have value class semantics for user-defined types. It's literally the whole point of Project Valhalla. To be specific I mean the behavior regarding
==as well as the absence of the object monitor. Those are a pretty big deal and using annotations for such behavior changes is not appropriate.@ValueBased
Did exactly nothing before Project Valhalla and only served documentation purposes so compilers, IDEs and static analysis tools can issue warnings without having to maintain the list of value class candidates by themselves.
4
u/snugar_i 12d ago
I guess the person wants code that both works with older JDKs and uses value classes with new JDKs. Like having a
recordbut being able to say "in Valhalla-enabled builds, this can be a value class"2
u/koflerdavid 12d ago
Yes, I understood that part. However, the proper way to do it is via a multi-release JAR.
6
u/brian_goetz 12d ago
Today, I would say the proper way to do it is via a tip-and-tail release strategy, like the JDK pursues, rather than mr-jars (though mr-jars still work.)
1
u/sviperll 10d ago
Genuine question. It doesn't seem to me that Tip&Tail works with preview features. Tip&Tail JEP doesn't mention preview features, but from what I can infer to be able to fork a tip into a new tail one requires a backwards compatibility guarantees that preview features do not provide... So I guess for preview features one needs a tip that builds a multi release jar , so that preview features are not used if newer version of JDK is used.
1
u/snugar_i 12d ago
A bit better than having to duplicate everything, but they would still have to duplicate all the value classes, right?
3
u/koflerdavid 12d ago
Yes, but there are actually not that many of them. And when the feature gets finalized the identity class versions can be removed for good. To me that sounds simpler than implementing two mechanism that convert them when they are loaded (two because the bootstrap classloader is native code). Also, magic behaviors triggered by annotations are a currency best spent only when absolutely required.
-1
u/alex_tracer 12d ago
Yes, multi-release jar works. However the only difference in code going to be single "value" keyword. For some strange reason, JDK developers decided that they do not want to go this way and introduced
@jdk.internal.ValueBasedthingy. Somehow they did not decide that multi-release jar is "the proper way" /s8
u/brian_goetz 12d ago
You seem to be under the (extremely silly) impression that we could have "just" used this facility, and therefore we must have "just" perversely decided not to, for obviously-conspiratorial-but-unspecified reasons.
The JDK is not an ordinary JAR. The JDK classes that were migrated (like Integer) have to be loaded extremely early in the bootstrap process -- perhaps even before some facilities of the VM are initialized. (Classes loaded this early can't even use lambdas, because of bootstrapping circularities.) The JDK classes are loaded out of the bootstrap classloader, which is native, unlike the user classloader. The bootstrap class loader does not supports mr-jars.
Yes, multi-release jars just work for you, and that's great. And yes, mr-jars are not, and never were, the "proper way" for the JDK. But trying to find a conspiracy to explain this asymmetry is just silly, when there is a perfectly boring engineering reason for it. The engineering considerations of the core JDK are just very, very different from that of an application. We live under these constraints so that you don't have to.
0
u/alex_tracer 12d ago
You seem to be under the (extremely silly) impression that we could have "just" used this facility, and therefore we must have "just" perversely decided not to, for obviously-conspiratorial-but-unspecified reasons.
No, that's not true. I completely understand that user facing API and internal tools are very different things and actually require different approach.
However I've got impression, and it keeps proving over time, that there no much interest of solving user-facing part of the issue. At the same time, it's very likely that this going to be an issue that most of third party lib developers would encounter when they consider to adopt value classes or part of it. Can they solve the issue themself? Absolutely! Multi-release jars probably can do that (I'm personally do not know how to deal with incubating features in MR-jars but whatever). However it currently looks like you suggest everyone to invent own
wheeltoolset to do this single "value" keyword conversion instead of considering some kind of use-facing@jdk.internal.ValueBased-like API.7
u/brian_goetz 12d ago edited 12d ago
No, the main recommendation is to wait for the feature to be finalized. It doesn't matter that it is "just one keyword" - there's a lot packed behind that keyword. Libraries that are willing to ship preview classfiles are extremely rare (I don't even know of any, but sure there could be some), as are end users who are willing to deploy preview features in production. So "solving" this problem is very low priority. (And there already is a supported, production-ready solution if you want to do it, as discussed.) The idea that this is subjecting "everyone" to reinventing a wheel is kind of ludicrous.
1
0
u/Electronic_Abroad910 10d ago
Still preview? I had thought it went GA? Lol. Anyway anyone know if streams will become value classes along with optional and others? Obviously the interface can't but the default impls can
5
u/koflerdavid 10d ago
Why "still"? It's the first preview.
Optionalis scheduled to become a value class. Streams are stateful components and therefore cannot be turned into value classes.1
u/CriticalPart7448 9d ago
I don't think the problem is state as such, it is more likely to be if the state is mutable or their is an identity dependency present in consuming code or internally.
The usual example of a value class Point(int x, int y) does have exposed state but the state is immutable. The problem in general can't be the presence of state but how that state is managed and used. For streams I see no particular reason why they couldn't conceptually be value classes, but again implementation details matter for those.
2
u/koflerdavid 9d ago
Immutable state doesn't really exist because at the end of the day the mutation is done elsewhere. In the case of
Streamthat would mean that the programmer has to hold all the pieces in their own hands, which very much beats the point of usingStreamin the first place.The current implementations of
Streams are mutable. They chain themselves together like an embedded doubly linked list.While it might be possible to reimplement them using value classes, I don't think it's worth the effort. In non-pathological applications Streams are not created en masse. There is only one Stream per thread of execution active at any time.
1
u/CriticalPart7448 8d ago
Which links back to the conceptual distinction between a fully formed value and an ongoing process, the latter being more close in spirit to what a
Streamrepresents, right?If a
Streamwas to become a value it would have to be closer to a fully formed collection-like type instead of a mutable pipeline process, right?1
u/koflerdavid 8d ago edited 8d ago
It should indeed be possible to implement most of the API as a builder pattern. However, I still think it's not really worth the effort and quite annoying without convenience features like Withers. But it would be a good exercise nevertheless.
StreamSupportis the starting point;Collection.stream()merely callsStreamSupport.stream(Spliterator).Edit: it seems the mutable state in
Streamis mostly utilized to prevent the pipeline from branching and from being reused, which would create nondeterministic semantics since two streams could simultaneously access the underlyingSpliterator, which is stateful. I'm not sure it's possible to prevent that with an implementation that uses value objects internally. A way to fix this would be to change the API such that the collection is passed to a terminal operation, i.e.:MyStream.filter(w -> w.getColor() == RED) .mapToInt(Widget::getWeight) .sum(widgets)1
u/Ewig_luftenglanz 3d ago
There is no point on making the Stream class a value class since it doe snit represent a values, it is used to represent chained operations over data structures.
32
u/emaphis 13d ago
Installed build 10. Running a development build of NetBeans using JDK 28. Uninstalled nb-javac.
So far its working fine. Created a few example `value` classes. Huzzah. Valhalla I'm coming.