<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sebastien Le Roy</title>
    <description>The latest articles on DEV Community by Sebastien Le Roy (@sebastien_leroy_ea5abcf2).</description>
    <link>https://dev.to/sebastien_leroy_ea5abcf2</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3370791%2Fe3f9e36f-c798-443c-8c73-ddb3ef0db757.jpg</url>
      <title>DEV Community: Sebastien Le Roy</title>
      <link>https://dev.to/sebastien_leroy_ea5abcf2</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sebastien_leroy_ea5abcf2"/>
    <language>en</language>
    <item>
      <title>The JVM / JDK ecosystem</title>
      <dc:creator>Sebastien Le Roy</dc:creator>
      <pubDate>Mon, 10 Nov 2025 21:06:53 +0000</pubDate>
      <link>https://dev.to/sebastien_leroy_ea5abcf2/the-jvm-jdk-ecosystem-efn</link>
      <guid>https://dev.to/sebastien_leroy_ea5abcf2/the-jvm-jdk-ecosystem-efn</guid>
      <description>&lt;p&gt;In the previous post, we discussed the Shenandoah Garbage Collector and I mentioned some distributions to explicit if this garbage collector is supported or not.&lt;/p&gt;

&lt;p&gt;There is an element of confusion when we talk about JDK, JVM, Hotspot… as these terms are often referenced but not always well described, and unfortunately sometimes not used correctly. The goal of this post is to try to clarify the terms and try to describe the current ecosystem.&lt;/p&gt;

&lt;p&gt;We need to introduce three different concepts:&lt;br&gt;&lt;br&gt;
– JVM&lt;br&gt;&lt;br&gt;
– Implementation SDK&lt;br&gt;&lt;br&gt;
– Distribution SDK&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqpeg8ogwm7g6c20eta6w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqpeg8ogwm7g6c20eta6w.png" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The JVM
&lt;/h3&gt;

&lt;p&gt;The Java SE has a set of specifications (Language + JVM) that is lead by Oracle. They decide how the language evolve.&lt;/p&gt;

&lt;p&gt;What we call a JVM in the everyday language is usually an implementation of the JVM specification. The job of the JVM is to execute the Java bytecode (compiled .class files). In the JVM we will find the class loading, execution of the bytecode, the Just In Time compiler, the memory management and different garbage collectors….&lt;/p&gt;

&lt;p&gt;There are three main JVM implementations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hotspot&lt;/strong&gt; : it is by far the dominant JVM, developed by Oracle&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;J9&lt;/strong&gt; : an alternative JVM that was originally developed by Oracle. Its goal was to optimize the memory footprint, the startup performance to have a JVM better fitted for enterprise-scaled applications. It was later donated to the Eclipse Foundation and now exists under the name &lt;strong&gt;OpenJ9&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GraalVM&lt;/strong&gt; : an alternative JVM developed by Oracle Labs with 2 main goals: replace the old Hotspot C2 compiler by a new compiler written in Java (Graal compler) so that it can be further developed and optimized and open the JVM to other languages (Python, Rust…). GraalVM is based on hotspot with some twists (different compiler + polyglot engine) rather than a full different JVM.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These 3 JVMs have a different profile and will fit different needs differently. The J9 JVM is known for consuming less memory but with the trade-off or lower throughputs, so it may be a good fit for containerized environments with less memory available.&lt;/p&gt;

&lt;h3&gt;
  
  
  The implementation JDK
&lt;/h3&gt;

&lt;p&gt;To have a complete developer environment, we need to add on top of the JVM:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The core Java libraries (&lt;code&gt;java.lang&lt;/code&gt;,&lt;code&gt;java.util&lt;/code&gt;, &lt;code&gt;java.io&lt;/code&gt;…)&lt;/li&gt;
&lt;li&gt;The tooling to compile the code into bytecode (&lt;code&gt;javac&lt;/code&gt;, &lt;code&gt;jar&lt;/code&gt;…)&lt;/li&gt;
&lt;li&gt;The supporting infrastructure to ease the developer experience: troubleshooting looks like JFR or &lt;code&gt;jcmd&lt;/code&gt;, the JMX APIs, the certificate management tools like keytools or cacerts…&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The implementation JDK provides an implementation for all the above and embeds the JVM. Each JVM has its own implementation JDK:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hotspot -&amp;gt; OpenJDK&lt;/li&gt;
&lt;li&gt;OpenJ9 JVM -&amp;gt; OpenJ9 JDK&lt;/li&gt;
&lt;li&gt;GraalVM JVM -&amp;gt; GraalVM JDK&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As for the JVM, the JDKs provide different tooling options. For example, GraalVM is famous for its AOT and native image compilation capabilities that reduce the memory footprints of the application and speed up startup time.&lt;/p&gt;

&lt;h3&gt;
  
  
  The distribution JDK
&lt;/h3&gt;

&lt;p&gt;Now that there is a project providing an implementation of the JDK, it still needs to be packaged, tuned, tested, supported and patched. That is what the distribution provides.&lt;/p&gt;

&lt;p&gt;There are a lot of distributions: some require a paid license and provide enterprise reliability, guaranteed long term support, certified builds, some are open source. At the distribution level, some vendors decide to disable some features that they do not want to support (ZGC, Shenandoah GC, experimental JVM options), tune the heap flags differently or provide extra crypto algorithms, telemetry agents or diagnostic tools.&lt;/p&gt;

&lt;p&gt;I hope this article helped to clarify the difference between an implementation of the SDK and a distribution. It highlighted that there are alternatives to the traditional HotSpot JVM / OpenJDK and we’ll try OpenJ9 and GraalVM in practice. That will be the subject of future articles.&lt;/p&gt;

</description>
      <category>uncategorized</category>
      <category>java</category>
      <category>programming</category>
    </item>
    <item>
      <title>New in Java25: Generational Shenandoah GC is no longer experimental</title>
      <dc:creator>Sebastien Le Roy</dc:creator>
      <pubDate>Sun, 14 Sep 2025 13:25:54 +0000</pubDate>
      <link>https://dev.to/sebastien_leroy_ea5abcf2/new-in-java25-generational-shenandoah-gc-is-no-longer-experimental-539g</link>
      <guid>https://dev.to/sebastien_leroy_ea5abcf2/new-in-java25-generational-shenandoah-gc-is-no-longer-experimental-539g</guid>
      <description>&lt;p&gt;This article kicks off a series of posts related to the release of the new Java 25. We will focus on the changes that can impact application performance. In this post, we will focus on the Shenandoah garbage collector (GC) which now officially supports a generational algorithm.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the Shenandoah GC ?
&lt;/h2&gt;

&lt;p&gt;The Shenandoah GC is one of the garbage collectors provided on the HotSpot JVM that can be enabled to manage the memory of the JVM. The following table lists the existing garbage collectors and their main usage for Hotspot:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Garbage Collector&lt;/th&gt;
&lt;th&gt;Usage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Serial GC&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Single-threaded collector, best suited for single-core machines or small applications&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Parallel GC&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Multi-threaded collector focused on maximizing throughput&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Concurrent Mark-Sweep&lt;/strong&gt; 🕱&lt;/td&gt;
&lt;td&gt;Removed in JDK14&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;G1 GC&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Designed to balance latency and throughput. Default GC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ZGC&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Low-latency scalable collector with sub-millisecond pause times&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Shenandoah&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Low-pause-time collector like ZGC, also concurrent compaction.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;No-op GC&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Test only. Allocates memory but never reclaims it. Useful for testing and performance evaluation without GC overhead&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The Shenandoah GC was introduced in 2019 with Java 12, and aims at providing a guaranteed low pause time for latency-sensitive applications. What you can expect with this GC is a pause time in the 1-10 milliseconds range, independently of the heap size.&lt;/p&gt;

&lt;p&gt;To achieve this low level of pauses, the GC is almost fully concurrent. The memory is divided into regions, and the GC works to mark, evacuate and compact objects in some of the regions while the application is running. There is a small “stop the world” pause at the end of a collection cycle, but it is brief as most of the tasks were done while the application is running.&lt;/p&gt;

&lt;p&gt;Let’s see how it compares with the other GC:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;G1GC&lt;/strong&gt; is the default garbage collector since JDK 9 because it is the most balanced garbage collector between throughput, memory usage and latency. G1GC is also a region-based garbage collector, but it only performs the marking phase while the application is running and needs to pause the application to perform the compaction phase. That explains why Shenandoah can provide lower latencies than G1GC (~200ms). The tradeoff is that Shenandoah requires more memory (10-20% overhead on the heap) compared to G1GC (&amp;lt;10%)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ZGC&lt;/strong&gt; is a very interesting GC to compare with Shenandoah as they are both designed to be low-pause garbage collectors. So why do we have both ? Because they have been concurrently developed by different actors. ZGC has been developed by Oracle and released since JDK 11. Shenandoah has been developed by Red Hat and released since JDK 12. The Oracle JDK does not include Shenandoah in an effort to promote their own ZGC.&lt;br&gt;&lt;br&gt;
Even if they are both low-pause GC, Shenandoah has been designed for medium-sized heaps (8 to 64GB) while ZGC is designed for extra large heaps (hundreds of GBs and beyond).&lt;/p&gt;
&lt;h2&gt;
  
  
  What is the generational Shenandoah?
&lt;/h2&gt;

&lt;p&gt;Generational GCs were developed based on the observation that most “objects die young” in the heap, and if these objects are not dead after a few collection cycles, there is no point checking them at every single collection because they will most likely live very long.&lt;/p&gt;

&lt;p&gt;To reduce the collection cycle, Generational GCs split the heap into a space for recent objects (young) and a space for objects that survived a few cycles (old). The collection strategies differ for these different generations, which removes unnecessary scans and improves performance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fav2d1hiv1aktfwiqrsu4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fav2d1hiv1aktfwiqrsu4.png" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All mature GCs are generational, but the generational feature is often added after the initial release of the GC. ZGC was released in 2018 and added the generational feature in JDK 23. Remember that ZGC and Shenandoah are competitors and follow the same trajectory, so it was not a surprise to see the Generational Shenandoah released in JDK 24 as an experimental feature.&lt;/p&gt;

&lt;p&gt;The generational Shenandoah should mostly improve the throughput and the memory footprint compared to non-generational Shenandoah. I have heard the number of ~30% higher throughput, but did not find any precise benchmark to corroborate this number.&lt;/p&gt;
&lt;h2&gt;
  
  
  What has changed for Shenandoah GC in Java 25 ?
&lt;/h2&gt;

&lt;p&gt;In Java 24, the Shenandoah GC generational algorithm was released as an experimental feature, so that its correctness can be proven. You can use it in Java 24 using the following flags:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational
-XX:+UnlockExperimentalVMOptions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Between Java 24 and 25, the work continued on this GC to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stabilize the implementation&lt;/strong&gt; and fix bugs and security issues&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improve performance&lt;/strong&gt; by reducing scanning, GC overhead and reduce the variability of pauses&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimize region handling&lt;/strong&gt; to avoid promoting short-lived objects&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Improve tooling and logging&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks to all these improvements, the Generational Shenandoah has now reached a level of maturity that makes it suitable for production-grade applications, and has been made an official feature. That means that if you were using it in Java 24, you do not need the experimental flag anymore, and if you were using the Shenandoah GC without the generational feature, it may be worth considering it.&lt;/p&gt;

</description>
      <category>uncategorized</category>
      <category>java</category>
      <category>java25</category>
    </item>
    <item>
      <title>⚡️ Spring Boot Performance: Avoid Default Config Pitfalls</title>
      <dc:creator>Sebastien Le Roy</dc:creator>
      <pubDate>Sat, 19 Jul 2025 20:52:03 +0000</pubDate>
      <link>https://dev.to/sebastien_leroy_ea5abcf2/spring-boot-performance-avoid-default-config-pitfalls-406b</link>
      <guid>https://dev.to/sebastien_leroy_ea5abcf2/spring-boot-performance-avoid-default-config-pitfalls-406b</guid>
      <description>&lt;p&gt;Spring Boot makes it easy to get started, but its default settings can quietly sabotage your performance&lt;/p&gt;

&lt;p&gt;In this article, I explore real-world pitfalls in Spring Boot’s default configuration&lt;/p&gt;

&lt;p&gt;&lt;a href="https://theperfparlor.com/2025/07/18/spring-boot-performance-avoid-default-config-pitfalls/" rel="noopener noreferrer"&gt;Read the article&lt;/a&gt;&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>performance</category>
      <category>java</category>
      <category>kotlin</category>
    </item>
  </channel>
</rss>
