Earlier quoted context omitted.
First, your parent comment misunderstood what the section they were critiquing is referring to. It's not about nullability (which is orthogonal) but about reference/value projections. Now, as a member of the Java team (although I'm not directly involved in Valhalla), I'm obviously biased so let me just say that both designers and fans of programming language features would do well to remember two things: 1. Opinions…
This is pretty funny... "All differences are opinions....except what .net did. Those are wrong!" I personally think Java continues to to waste a lot of time and come to a slightly more verbose and worse solution again and again. Structured concurrency is like c# async/await with less sugar. Streams are just LINQ but worse. It's probably exactly because of the "not like .NET! We must be different to explain being late…
They have different philosophies though, C# is mostly "give the developer a complex toolkit so they can do whatever they want, but keep the runtime simple", while Java is more like "keep the language as simple as possible, and put new features mostly into the runtime making it more complex, but benefiting even old code".
Async vs virtual threads is a clear example of that. The former makes the language much more complex, and has a huge surface area where it may clash with other features, so a developer has to remember all of these. But it's a simple machinery under the hood.
Meanwhile virtual threads don't change the language at all, it's the same as it was with Threads, but under the hood it is a very complex feature.
And in this particular instance I think it is quite clear cut that Java made the correct decision, for the most common use case of these languages having non-blocking IO "automatically" makes for significantly better user experience.