Devoxx 2023 was held in Antwerp, Belgium, and highlighted many important topics of the Java world. Here I’m trying to put it all together. One of the main purposes of this article is to have one place with all the interesting links, which I can visit myself later.
All talks are already available on the Devoxx YouTube channel. Here is the playlist of the deep-dive sessions (sometimes really “deep”), and here are the recordings of the main part of the conference.
Java 21
Virtual threads
https://docs.oracle.com/en/java/javase/21/core/virtual-threads.html
In my opinion, this is the most important feature, released in Java 21. A virtual thread is not directly bound to an exact OS thread but to a carrier thread, which will be freed as soon as we bump into a blocking operation. Virtual threads are very lightweight and quick to start, which allows you to create millions of them. They have the same old contract as the usual Thread. In fact, Thread.ofVirtual().start()gives you already familiar old java.lang.Thread. Also if you use Spring Boot of version 3.2 or above, you can easily turn on virtual thread pools by just setting the property: spring.threads.virtual.enabled=true.
One drawback you should remember when switching your whole app to virtual threads (e.g. like switching the property as described above) is the usage of ThreadLocal-s. They’re tightly coupled to old OS threads, which doesn’t allow a virtual thread to be easily freed up when a blocking operation is run. Check out the excellent talk by Mario Fusco about it.
Pattern matching is going to the next level
Just look at what is possible now with Java 21:
1 2 3 4 |
var animal = (Object) new Dog (); if (animal instanceof Dog fido ){ fido.bark(); } |
or:
1 2 3 4 5 6 7 8 9 |
sealed interface Animal permits Bird, Cat, Dog {} String communicate(Animal animal) { return switch (animal) { case Cat cat -> cat.meow(); case Dog dog -> dog.bark(); case Bird bird -> bird.chirp(); }; } |
And there are many more which were impossible before. It all leads us to the Data Oriented Programming in Java, which provides an easier way to separate a data model from the business logic. You can read about it in the article by Brien Goetz or watch the deep-dive session by José Paumard and Remi Forax.
Future of Java: Projects Leyden and CRaC
Project Leyden targets the improvement of the startup and warmup of Java applications. It will provide you the so-called condensers – the tools in the JDK, that will move some of the computations to the compile time. Actually, you can think of it as an extension of the AppCDS, which has been available since JDK 5 (yes, it’s “five”). By passing parameters -XX:DumpLoadedClassList, -XX:SharedClassListFile and -XX:SharedArchiveFile when running your tests or an app itself, AppCDS will archive/cache metadata of the system classes, application classes, dynamically generated lambda proxies and many more. The next startup will use this archive and can be 20-30% quicker. And a very important thing is that you don’t need to apply any changes to the application code. More information about the project Ledyen is in Brien Goetz’s talk.
Project CRaC is about the checkpoint mechanisms – basically, it allows you to create a snapshot of a running application, then as an option, you can pass this snapshot to another similar machine and run it there. The same as the project Leyden it can be a solution to quicker startup and warmup of the applications. The Spring framework integrates CRaC since version 6.1: ApplicationContext receives notifications about checkpoints and restores and propagates them to the Lifecycle beans.
More links to check
- https://spring.io/blog/2023/09/20/hello-java-21 – an excellent article by Josh Long about how to install Java 21 and all the most important new things
- https://docs.oracle.com/en/java/javase/21/core/virtual-threads.html – the official Oracle documentation on virtual threads
- https://www.youtube.com/watch?v=eXCx2hW_xNI – a presentation by Brien Goetz about Java 21 and the future
Spring
I’ve already mentioned the Spring framework multiple times in the Java section above. If you want to dive deeper into all those Java features applied to the Spring framework, take a look at the presentation by Juergen Hoeller, Sébastien Deleuze and Arjen Poutsma. For example, Sébastien shows 2 interesting examples of how to create CRaC checkpoints onRefresh:
1 |
java -Dspring.context.checkPoint=onRefresh -XX:CRaCCheckpointTo=$CRaC_Files_Dir -jar myApp.jar |
or after startup:
1 2 3 |
java -XX:CRaCCheckpointTo=$CRaC_Files_Dir -jar myApp.jar # make your app work, e.g. launch some load testing jcmd myApp.jat JDK.checkpoint |
and restore it later during startup:
1 |
java -XX:CRaCRestoreFrom=$CRaC_Files_Dir |
But remember to be careful about sensitive information, because the checkpoint file will contain everything that was in memory when an application was running.
GraalVM
It’s an enormous topic to cover. GraalVM includes the JDK, the just-in-time compiler (the Graal compiler), Native Image, and standard JDK tools. You can use the GraalVM JDK just like any other JDK and run any Java application unmodified.
Using GraalVM Native Image you can compile Java code ahead-of-time into a platform-specific, self-contained native executable. It processes your application classes and other metadata to create a binary for a specific operating system and architecture. First, the native-image tool performs static analysis of your code to determine the classes and methods that are reachable when your application runs. Second, it compiles classes, methods, and resources into a binary. This entire process is called build time to clearly distinguish it from the compilation of Java source code to bytecode. Check the deep-dive session (at the end it was “very deep”) by Alina Yurenko and Fabio Niephaus to learn everything you’ll probably need about GraalVM Native Image. And another talk definitely worth mentioning is Spring AOT and native image by Josh Long and Alina Yurenko. Here you can find the github repo they used at the presentation.
Nobody argues, that the startup time is important and that GraalVM Native Image definitely beats the C2 JIT compiler. However, there are many discussions about the peak performance comparison. Which app would perform better – warmed-up app compiled by JIT or a Native executable. Check out the Medium article by Alina Yurenko, where she shows that by using the profile-guided optimizations (PGO) GraalVM Native Image can actually outperform JIT:
Other interesting talks and links
- JetBrains is working on an amazing feature – AI assistant, which will be built-in to the IDE (guess what’s the IDE). Just watch a short talk at the keynote session by Anton Arhipov to see what they already have in the preview mode.
- Spring AOT by Josh Long – all you need to know is in one GitHub repo.
- Two useful tools I haven’t heard about before the Devoxx: wrk – HTTP benchmarking tool and psrecord – the CPU and memory activity recorder of a process
Thank you very much for such a great review!
Spring is awesome! Moreover, with a GraalVM features! I can’t wait to test it!