The Java garbage collector: an up-to-date guide (Java 25)

There are many posts about the Java garbage collector, and many of them are old: PermGen, CMS, -XX:+PrintGCDetails… This guide sums up what is true in Java 25, in a few lines per topic. Each part links to a longer post, where every fact is checked in the official documentation or on a real JVM. I update this guide when the series moves on, or when a new Java version changes the rules. ...

October 22, 2026 · 6 min

Common myths about the Java garbage collector

You still read a lot of advice about the garbage collector. Some of it was wrong from the start, and some of it is not true anymore. Here are five common myths, and what the official documentation and a real JVM say in Java 25. “System.gc() forces a GC” No: it is a request, not an order. The javadoc says that System.gc() “suggests” that the JVM frees memory, with no guarantee about how much is freed, or even that the work is done at all. ...

October 22, 2026 · 4 min

JVM options that matter, and the ones that no longer work

You take an old startup script, you move to Java 25, and the JVM does not start anymore: Unrecognized VM option 'PrintGCDateStamps' Error: Could not create the Java Virtual Machine. Error: A fatal exception has occurred. Program will exit. Many memory and GC options that you still find on the web have changed or are gone. Some are just ignored, others stop the JVM at startup. And the options that are useful today fit in a few lines. ...

October 22, 2026 · 5 min

Java garbage collectors in 2026: which one is running yours?

Your application may be running with a different GC than you think. In Java 25, G1 is the default garbage collector. But the JVM offers others, each one for a different need. And on a small machine, it picks another one on its own. The GCs available in Java 25 GC What Oracle’s guide says Option Serial One thread does all the GC work. For a small data set (up to about 100 MB) or a single processor -XX:+UseSerialGC Parallel The “throughput collector”: like Serial, but with several threads. When raw performance comes first and pauses of a second or more are fine -XX:+UseParallelGC G1 A “mostly concurrent” collector: it does part of its work while the application runs. When response time matters more than throughput -XX:+UseG1GC ZGC Pauses under a millisecond, at the cost of some throughput. When low latency is the priority -XX:+UseZGC Shenandoah Another low-pause GC. Oracle’s guide does not cover it; it works on Temurin 25 -XX:+UseShenandoahGC And a special one: Epsilon. It allocates memory but never frees it. When the heap is full, the JVM stops. It is meant for tests (measuring an application without any GC, checking that a test does not create too many objects) or very short jobs. In Java 25, it is still experimental: you need -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC. ...

October 22, 2026 · 4 min

GC generations and cycles: young, old, minor, major, full

Minor GC, major GC, full GC: you see these words everywhere, but not always with the meaning the official documentation gives them. Most objects die young. So the JVM keeps new objects in the young generation and long-lived ones in the old generation. A GC that only cleans the young generation is fast, and it runs often. Why generations? Oracle’s official guide to the garbage collector starts from a simple fact: most objects live for a very short time. This is called the generational hypothesis. An object created for a request, a loop or a calculation is useless almost right away. ...

October 22, 2026 · 6 min

JVM memory: heap, stack and Metaspace

Does your old Java configuration fail to start on Java 17? The answer is in how the JVM uses memory. In Java, each thread has its own stack for local variables. Objects live on the heap, the area the garbage collector cleans up. Class data lives in the Metaspace, outside the heap. The JVM also uses other memory areas that are easy to forget. Three areas you need to know Memory of a Java process: thread stacks, the heap, the Metaspace and other native memory areas Java process everything outside the heap is native memory Stacks one per thread · -Xss Thread main process() · client main() Thread 2 read() run() frames, local variables Heap shared · managed by the GC · -Xmx Client String List byte[] objects created with new interned strings static fields Metaspace native memory no limit by default Client fields, methods… String fields, methods… class descriptions -XX:MaxMetaspaceSize Also in native memory Code cache machine code from the JIT up to 240 MB by default Direct memory ByteBuffer.allocateDirect() -XX:MaxDirectMemorySize Internal data garbage collector, compiler and more The stack: one per thread Each thread gets its own stack. Every method call adds a frame to it, with the method’s parameters and local variables. When the method returns, its frame is gone. The garbage collector is not needed to free this memory. ...

October 22, 2026 · 5 min

One Chrome per Google account on macOS

All day long, I have two Chrome windows open: my personal profile (Gmail, my accounts) and my work profile (a Google Workspace account for the company). On macOS, this is annoying. The problem On macOS, all Chrome profiles live in one app. The Dock and Cmd+Tab group windows by app. So: the Dock shows one Chrome icon for all profiles; Cmd+Tab shows one Chrome. To go from the personal window to the work window, you need Cmd+`, the Window menu or Mission Control; in Mission Control, personal and work windows are mixed. I wanted something simple: one icon per account in the Dock, and one entry per account in Cmd+Tab. ...

October 22, 2026 · 7 min