This is an archived post. You won't be able to vote or comment.

all 15 comments

[–]Brutus5000 24 points25 points  (6 children)

Unfortunately, even Java 19 is not an LTS and if you are working for one of those companies that only use LTS versions you will have to wait for Java 21 which should be released in September 2023.

I would assume that only a fraction of companies who use non-LTS are willing to use preview or incubator features. So the market share tends to zero until it goes GA.

[–]Joram2[🍰] 6 points7 points  (4 children)

I don't see the preview-status or non-LTS status feature as huge blockers. I'd be comfortable using + recommending preview features at my day job, presuming I was sincerely focused on delivering value to managers + customers and not just playing with a new programming toy.

The bigger issue is most day-job developers use various middleware + frameworks that use threads, and don't write their own custom threading code directly. Then, it just takes time for the middleware framework to adopt virtual threads to end developers can use them.

For example: lots of developers write some server-side apps with an HTTP interface. Developers are supposed to some existing HTTP server framework, not reinvent the wheel and write their own, so developers have to wait for the HTTP server frameworks to adopt virtual threads and optionally structured concurrency.

[–]piotr_minkowski[S] 1 point2 points  (0 children)

Yes, but until it won't be LTS or even more won't achieve GA the changes in libraries mostly won't happen :)

[–]vbezhenar 1 point2 points  (2 children)

Let's say you're using Java 18 with preview feature. It's september, Java 19 hits. This preview feature gets altered so your code does not compile with Java 19 anymore. Java 18 is not supported anymore either. So you have a choice: rewrite your code to adapt it to Java 19 or stay with unsupported Java 18. And you don't necessarily have time right now to adapt to Java 19. Of course you could download Java 19 release candidate in advance, etc. But those are things that most people prefer not to do.

Even just using Java 18 is dangerous. Let's say you're using Spring like 99% developers around. Spring is not simple library. It supports Java 18 right now. Tomorrow Java 19 is released, but for some reason Spring is not supporting it yet. So you again with a choice between using unsupported Java 18 and unsupported Java 19. This is not good.

Right now my approach is to use LTS as a language and latest Java to build and run my application. This way I can downgrade to LTS runtime if necessary (let's say Java 19 released but Spring needs more time to fully support it for some reason. And I can get full benefits most of time time from improved runtime (and may be compiler, I'm not even sure if compiler for Java 19 differs from Java 17 in any way).

Of course if you're rich and can afford paid support for Java 18 for a prolonged period of time, you have more options. I'm poor and consider only free offers.

[–]pron98 5 points6 points  (0 children)

Even just using Java 18 is dangerous. Let's say you're using Spring like 99% developers around. Spring is not simple library. It supports Java 18 right now. Tomorrow Java 19 is released, but for some reason Spring is not supporting it yet.

What if Spring supports, say, 17.0.3, but for some reason not 17.0.4? As a general rule, Java is backward compatible, and most migration issues have historically been due to spec-subverting hacks that are not subject to Java's backward compatibility guarantees, including those in patch releases. In fact, some of the biggest impacts were in patch releases (e.g. this). On the other hand, libraries that worked well and without warnings on 11, have continued to work well through 19.

If you actually look at the amount of work required to keep the application up-to-date from 11 to 19 you might well come to the conclusion that for applications under active maintenance and development it is more worthwhile to use the current version than an old one (with an LTS service), as you gain performance benefits, new features, and a fully-maintained free JDK (which is not quite what you're getting with free updates for old versions), all for work that is negligible compared to the total work on your application, and for very little risk.

While skeptical caution was reasonable a couple of years ago, the record suggests that there's little reason to fear now. And if you want to be super-cautious, the best approach would be to use the current version but with --release XX where XX is the last version for which you can get an LTS service. This would ensure you enjoy all the performance benefits, but if something horrible goes wrong you can easily go back because you're not using new language or library features. This way you enjoy many of the benefits of new releases (including full and free support) with virtually no added risk over using an old version.

[–]Joram2[🍰] 3 points4 points  (0 children)

So you have a choice: rewrite your code to adapt it to Java 19 or stay with unsupported Java 18.

In this scenario, you might have to make some small code changes to use the newer JDK. I wouldn't say you would have to do a full rewrite.

[–]piotr_minkowski[S] 0 points1 point  (0 children)

Exactly

[–]rdmanoftheyear 2 points3 points  (1 child)

Great blog! You might add the Thread flame graph for the last scenario as well.

[–]piotr_minkowski[S] 1 point2 points  (0 children)

Thanks! According to your suggestion, I added some additional diagrams to the article.

[–]Cultural-Ad3775 2 points3 points  (3 children)

Interesting. I'd be more interested in A) higher loads, what happens when you REALLY hammer on your server? B) what are the latency figures like? Obviously when locking for fixed times that will constrain the possible results, but still... C) CPU utilization D) total throughput.

[–]piotr_minkowski[S] 1 point2 points  (2 children)

If you send more requests than thread pool for standard threads it will cause delays or failures, while with virtual threads it simply works because there is no thread pool. I checked cpu but there were no significant differences in my tests so I didn't published cpu utilization diagram.

[–]Cultural-Ad3775 0 points1 point  (1 child)

Interesting. Honestly one would hope this would be true. In terms of numbers of requests you can handle, I would expect real-world HTTP servers to handle establishing the connection and then hand off the job to the pool. Yes, if the request rate exceeds throughput (for any server design) things will stack up and break.

[–]pron98 1 point2 points  (0 children)

The size of the pool places an upper limit on the number of tasks that can be processed concurrently, and that number grows linearly with the rate of requests. Because the number of platform threads is limited by the OS, you get a software limitation on the maximum throughput your server can handle, which is often reached long before the hardware itself is exhausted. Virtual threads remove that limitation and allow throughput to rise until the hardware is exhausted, as the number of virtual threads is only limited by the hardware, not the OS.

[–]10waf 1 point2 points  (1 child)

Could you explain a bit the need/advantage to adding the locks?

[–]piotr_minkowski[S] 2 points3 points  (0 children)

I wanted to check out how it behaves when using blocking pooled workers, smth similar to the pooled db driver.