Live data from Hacker News

Java 21: The Nice, the Meh, and the Momentous

horstmann.com

181–190 of 191 posts

Re: Java 21: The Nice, the Meh, and the Momentous

#181
post #91

Earlier quoted context omitted.

It's somewhat unfortunate that structured concurrency ended up being a preview feature in 21. I agree that it's a great addition but man it'd be nice if it made the LTS. As it stands, probably won't be heavily used until Java 25.

Organisations that care about new features need to reconsider their stance on using Preview features and even more importantly sticking to versions for which the sales org offers an LTS service. The whole concept of LTS is designed for companies that are so uninterested in new features (often because their software is no longer heavily maintained) that they're willing to pay money not to receive them. There are a lot…

While I tend to agree, it's just a losing battle (in my experience). The issue is that shockingly few people in organizations actually care about language improvements. Further, because orgs prioritize spitting out new features above all else, selling maintenance work like updating the JVM is seen more as pure waste than actual benefit to the company.

The one argument I've been able to make to get an update is "This has fallen out of support and will no longer get security updates". That seems to be the only motivator for my company to do updates.

Re: Java 21: The Nice, the Meh, and the Momentous

#182
post #164

Earlier quoted context omitted.

And where do you handle callbacks?

there are tons of variations, depending on your logic and API. The closest to virtual threads is ForkJoinPool and RecursiveTask, where you can have code like regular blocking code: var f = async_api_returns_future(); ... var res = f.join(); but join() won't block OS/JVM thread, but make it to perform other tasks in the queue. Or you can design API which will receive executorService as params, and run callback there,…

One way to see how different virtual threads are from our old mechanisms is to ask yourself how many IO operations you can have in flight. There are two options: either the operations are blocking, in which case the number will be equal to the (very limited) number of threads in all of your thread pools combined, or the operations are non-blocking, in which case thread context that is so necessary for troubleshooting and JFR profiles is lost (e.g. JFR can't know on behalf of whom is some IO operation performed because the "owner" of some operation -- in the design of the Java platform -- can only be a thread). Virtual threads allow you to have hundreds of thousands (or even millions) of I/O operations in flight (which you need for high throughput as a result of Little's law) while still preserving observable context.

BTW, as for fork-join's `join`, not only is it designed for pure computation only and cannot help with IO, but every `join` increases the depth of the stack, so it is fundamentally limited in how much it can help. FJ is designed for pure computation workloads, so in practice that's not a huge limitation, but virtual threads are designed for IO workloads.

I apologise for not going into more depth here, but as you can imagine, with a user base numbering in the many millions, we can only afford to put in depth explanations in texts and videos that gain a large audience, but once you've familiarised yourself with the material I'll gladly answer specific questions (and perhaps your questions will help us improve our material, too).

Re: Java 21: The Nice, the Meh, and the Momentous

#183
post #182

Earlier quoted context omitted.

there are tons of variations, depending on your logic and API. The closest to virtual threads is ForkJoinPool and RecursiveTask, where you can have code like regular blocking code: var f = async_api_returns_future(); ... var res = f.join(); but join() won't block OS/JVM thread, but make it to perform other tasks in the queue. Or you can design API which will receive executorService as params, and run callback there,…

One way to see how different virtual threads are from our old mechanisms is to ask yourself how many IO operations you can have in flight. There are two options: either the operations are blocking, in which case the number will be equal to the (very limited) number of threads in all of your thread pools combined, or the operations are non-blocking, in which case thread context that is so necessary for troubleshooting…

> I apologise for not going into more depth here, but as you can imagine, with a user base numbering in the many millions

my concern is that you somehow can find time to write long comments with lots of handwavings (our framework is designed for that, and their framework is not designed for that), but refuse to provide specific code pointers and example in support of your opinion. For example, in this specific case, can you give example how green threads can be used with current Java IO library, or Java JDBC library?

Re: Java 21: The Nice, the Meh, and the Momentous

#184
post #182

Earlier quoted context omitted.

One way to see how different virtual threads are from our old mechanisms is to ask yourself how many IO operations you can have in flight. There are two options: either the operations are blocking, in which case the number will be equal to the (very limited) number of threads in all of your thread pools combined, or the operations are non-blocking, in which case thread context that is so necessary for troubleshooting…

> I apologise for not going into more depth here, but as you can imagine, with a user base numbering in the many millions my concern is that you somehow can find time to write long comments with lots of handwavings (our framework is designed for that, and their framework is not designed for that), but refuse to provide specific code pointers and example in support of your opinion. For example, in this specific case,…

Virtual threads are just Java threads, so any blocking code using any API will just work. If you're looking for introductory material on virtual threads with specific examples you can find some here: https://openjdk.org/jeps/444, https://docs.oracle.com/en/java/javase/21/core/virtual-threa..., https://youtu.be/l_Vlz0wkG58?si=MF-XJW7c8T5jGf5i&t=1914

If there's something unclear in that material, please ask. Also, there is no our framework vs. their framework here. I'm only discussing the JDK's own various thread pools vs. virtual threads. They were all designed and implemented by the JDK team.

BTW, I'm not trying to support any opinion. Pretty much all popular Java server frameworks are adopting virtual threads, and Java's virtual threads are poised to become the most popular lightweight user mode threads. We've already convinced everyone that needed convincing. I'm merely offering pointers in case you're interested to learn how to use virtual threads and understand how they offer high throughput and good observability at the same time (whereas before you could have one or the other). Of course, if you're satisfied with the throughput and observability you can get with our old mechanisms, you don't have to use virtual threads. We've not taken anything away.

Re: Java 21: The Nice, the Meh, and the Momentous

#185
post #184

Earlier quoted context omitted.

> I apologise for not going into more depth here, but as you can imagine, with a user base numbering in the many millions my concern is that you somehow can find time to write long comments with lots of handwavings (our framework is designed for that, and their framework is not designed for that), but refuse to provide specific code pointers and example in support of your opinion. For example, in this specific case,…

Virtual threads are just Java threads, so any blocking code using any API will just work. If you're looking for introductory material on virtual threads with specific examples you can find some here: https://openjdk.org/jeps/444 , https://docs.oracle.com/en/java/javase/21/core/virtual-threa... , https://youtu.be/l_Vlz0wkG58?si=MF-XJW7c8T5jGf5i&t=1914 If there's something unclear in that material, please ask. Also, th…

There is this example in material:

try (var in = url.openStream()) { return new String(in.readAllBytes(), StandardCharsets.UTF_8); }

which claims that this example will scale well with virtual threads, my understanding is that in.readAllBytes() will call OS blocking socket API underneath, which will block OS thread, so you would need many OS threads to scale. Is this understanding correct?

Re: Java 21: The Nice, the Meh, and the Momentous

#186
post #184

Earlier quoted context omitted.

Virtual threads are just Java threads, so any blocking code using any API will just work. If you're looking for introductory material on virtual threads with specific examples you can find some here: https://openjdk.org/jeps/444 , https://docs.oracle.com/en/java/javase/21/core/virtual-threa... , https://youtu.be/l_Vlz0wkG58?si=MF-XJW7c8T5jGf5i&t=1914 If there's something unclear in that material, please ask. Also, th…

There is this example in material: try (var in = url.openStream()) { return new String(in.readAllBytes(), StandardCharsets.UTF_8); } which claims that this example will scale well with virtual threads, my understanding is that in.readAllBytes() will call OS blocking socket API underneath, which will block OS thread, so you would need many OS threads to scale. Is this understanding correct?

It is not. Blocking IO (with some exceptions mentioned in the JEP) will automatically be translated by the runtime into non-blocking IO when it occurs on virtual threads, and no OS threads will be blocked. The Java code will look blocking and that's what thread dumps and other Java observability mechanisms will show, but to the OS it will seem as if it's running non-blocking code.

You can have a million threads blocking on a million sockets (obviously without creating a million OS threads): https://github.com/ebarlas/project-loom-c5m

You can't do that with thread pools. You could achieve that scalability with async code, but then observability tools will not be able to track the IO operations and who initiated them, but with virtual threads you'll see exactly what business operation is doing what IO and why.

Re: Java 21: The Nice, the Meh, and the Momentous

#187
post #186

Earlier quoted context omitted.

There is this example in material: try (var in = url.openStream()) { return new String(in.readAllBytes(), StandardCharsets.UTF_8); } which claims that this example will scale well with virtual threads, my understanding is that in.readAllBytes() will call OS blocking socket API underneath, which will block OS thread, so you would need many OS threads to scale. Is this understanding correct?

It is not. Blocking IO (with some exceptions mentioned in the JEP) will automatically be translated by the runtime into non-blocking IO when it occurs on virtual threads, and no OS threads will be blocked. The Java code will look blocking and that's what thread dumps and other Java observability mechanisms will show, but to the OS it will seem as if it's running non-blocking code. You can have a million threads block…

> will automatically be translated by the runtime into non-blocking IO when it occurs on virtual threads, and no OS threads will be blocked

it looks like it is true for several API you implemented support for. What about other API, for example some JDBC driver which wants to use non-blocking DB driver. How to use virtual threads with that?

Re: Java 21: The Nice, the Meh, and the Momentous

#188
post #186

Earlier quoted context omitted.

It is not. Blocking IO (with some exceptions mentioned in the JEP) will automatically be translated by the runtime into non-blocking IO when it occurs on virtual threads, and no OS threads will be blocked. The Java code will look blocking and that's what thread dumps and other Java observability mechanisms will show, but to the OS it will seem as if it's running non-blocking code. You can have a million threads block…

> will automatically be translated by the runtime into non-blocking IO when it occurs on virtual threads, and no OS threads will be blocked it looks like it is true for several API you implemented support for. What about other API, for example some JDBC driver which wants to use non-blocking DB driver. How to use virtual threads with that?

JDBC drivers are implemented on top of JDK APIs and so will work the same way: their I/O would automatically be non-blocking when run on a virtual thread (module some quality-of-implementation issues around the use of synchronized that we're working on, which are mentioned in the material I linked to).

JDBC drivers that are implemented on top of their own native code are a different matter, but they are not common these days.

Re: Java 21: The Nice, the Meh, and the Momentous

#189

The examples having to word wrap in a tiny text box look even more absurd and unreadable when the page is only using 1/3rd of the screen. What is with this awful formatting? https://i.imgur.com/nQmt7Qo.png

It is easier to read something that is page-sized, as opposed to taking up the full screen. Although it does look weird.

Re: Java 21: The Nice, the Meh, and the Momentous

#190
post #158
post #124

Earlier quoted context omitted.

Those are not minor versions, that's quite natural path and is supported by every lib we used, except groovy. And this is the encouraged path for JDK upgrades, people are lazy, but not us :) Spring supports new JDK release ("minor version" like you called them, those between 11 and 17 and 21) before release. The only exception was with JDK 13, there was about 2 week slip there. Lombok (I don't like it) supports every…

I see your point... I've never upgraded to the non-LTS Java versions (almost no one is doing it - as you can see in any survey about it - which in itself is enough for me not to be the "brave" one doing it!) so I don't know how much pain that would've been. To me that just shows that Groovy could do with a bit more attention as I find it to be a great language, specially with Spock... it has made our tests so much ni…

It is a bit brave to upgrade every 6 releases or every 4, I prefer to have smaller issues more often than big ones rarely.

But I get that most of the time the issues is with dependencies that upgrade to lazily (that's why I don't like those that are bytecode magic and don't use ASM).

Post reply on HN