4 ms·
> Java's major competitors, C# and Go, both have had value types since day one Yes (well, structs; not really value types), but at a significant cost to FFI an
by pron 1y ago
> Java's major competitors, C# and Go, both have had value types since day one
Yes (well, structs; not really value types), but at a significant cost to FFI and/or GC and/or user-mode threads (due to pointers into the stack and/or middle of objects). Java would not have implemented value types in this way, and doing it the way we want to would have been equally tricky had it been done in Java 1.0. Reified generics also come at a high price, that of baking the language's variance strategy into the ABI (or VM, if you want). However, value types will be invariant (or possibly extensible in some different way), so it would be possible to specialise generics for them without necessarily baking the Java language's variance model into the JVM (as the C# variance model is baked into the CLR).
Also, C# and Go didn't have as much of a choice, as their optimising compilers and GCs aren't as sophisticated as Java's (e.g. Java doesn't actually allocate every `new` object on the heap). Java has long tried to keep the language as simple as possible, and have very advanced compilers and GCs.
> If the technical side isn't that hard, I'd have expected the JVM to have implemented value types already, making it available to other less conservative languages like Kotlin, while work on smoothly integrating it in Java took as long as needed
First, that's not how we do things. Users of all alternative Java Platform languages (aka alternative JVM languages) combined make up less than 10% of all Java platform users. We work on the language, VM, and standard library all together (this isn't the approach taken by .NET, BTW). We did deliver invokedynamic before it was used by the Java language, but 1. that was after we knew how the language would use it, and 2. that was at a time when the JDK's release model was much less flexible.
Second, even if we wanted to work in this way, it wouldn't have mattered here. Other Java Platform languages don't just use the JVM. They make extensive use of the standard library and observability tooling. Until those are modified to account for value types, just a JVM change would be of little use to those languages. The JVM comprises maybe 25% of the JDK, while Kotlin, for example, makes use of over 95% of the JDK.
Anyway, Project Valhalla has taken a very long time, but it's making good progress, and we hope to deliver some of its pieces soon enough.
- pjmlp 1y agoGo I agree, .NET is on par with JVM, even if they don't have the pleothora of choice regarding JVM implementations, and the ability to do C++ like coding means there isn't that much of a pressure for pauseless GC as in Java. Looking forward to Project Valhalla updates, I had some fun with the first EA.
- pron 1y agoI'm not sure what is meant here by "on par with the JVM." I'm not trying to claim that one or the other is better, but there is a basic difference in how they're designed and continue to evolve. .NET believes in a language that gives more control on top of a more basic runtime, while Java believes in a language that's smaller built on top of a more advanced runtime. They just make different tradeoffs. .NET doesn't "need" a more advanced runtime because limitations in its runtime can be overcome by more explicit control in the language; Java doesn't "need" a more elaborate language because limitations in the level of control offered by the language can be overcome by a more sophisticated runtime. I'm not saying these are huge differences, but they're real. C# has more features than the Java language, while Java's compiler and GCs are more sophisticated than the CLR's. Both of these differences are due to conscious choices made by both teams, and they each have their pros and cons. I think these differences are very apparent in how these two platforms tackled high-scale concurrency: .NET did it in the language; Java did it in the runtime. When it comes to value types, we see a similar difference: in C# you have classes and structs (with autoboxing); in Java we'll just have classes that declare whether they care about identity, and the runtime will then choose how to represent each instance in memory (earlier designs did explore "structs with autoboxing" but things have moved on from there, to the point of redefining autoboxing even for Java primitives; for a type that doesn't care about identity, autoboxing becomes an implementation detail - transparently made by the compiler - with no semantic difference, as a pointer or a value cannot be distinguidhed in such a case - hence https://openjdk.org/jeps/390 https://openjdk.org/jeps/390 - unlike before, when an Integer instance could be distinguished from an int).
- pjmlp 1y agoIt means that it does the same JIT optimization tricks that Hotspot performs, escape analysis, devirtualization, inlining method calls, removing marshaling layers when calling into native code, PGO feedback,.... I would like to someday have someone write blog posts about performance like the famous ones from the .NET team, and also not having to depend on something external like JIT Watch, instead of having it in box like .NET. Example for upcoming .NET 10, https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-10/ https://devblogs.microsoft.com/dotnet/performance-improvemen... Also C# and .NET low level programming features are here today, Project Valhala delivery is still in future, to be done across several versions, assuming that Oracle's management doesn't lose interest funding the effort after all these years. It is kind of interesting how after all these years, the solution is going to be similar in spirit to what Eiffel expanded types were already offering in 1986. https://wiki.liberty-eiffel.org/index.php/Expanded_or_reference https://wiki.liberty-eiffel.org/index.php/Expanded_or_refere... https://archive.eiffel.com/doc/online/eiffel50/intro/language/tutorial-07.html https://archive.eiffel.com/doc/online/eiffel50/intro/languag... I guess that is what happens when language adoption turns out to go in a different path than originally planned, given Java's origins.
- kbolino 1y agoThis has been a very informative discussion, so thank you for that. I did want to point out, though, that both languages have other (compound) value types than just structs. Go has value-based arrays, and C# has value-based tuples. It looks like C# may gain value-based discriminated unions as well, though it's not settled yet: https://github.com/dotnet/csharplang/blob/main/proposals/unions.md https://github.com/dotnet/csharplang/blob/main/proposals/uni...