Java in Docker and Kubernetes: avoid OOMKilled

The pod restarts. kubectl get pod shows OOMKilled, and the exit code is 137. But the logs show no OutOfMemoryError, and the heap was far from full. The JVM did not run out of memory: the container did. The Linux kernel killed the process because it went over its limit. This post shows what the JVM sees in a container, what adds to the heap, how to reproduce the kill, and how to set the memory so that everything fits. All the examples are in the containers/ folder of the public java-gc-lab repository. They use the official eclipse-temurin images: no image to build. ...

October 23, 2026 · 10 min

JFR, jcmd, VisualVM: which tool for Java memory problems

In this series, we have already used about six tools: GC logs, jstat, several jcmd commands, Eclipse MAT. Each one answers a clear question, and each one has a cost. This post puts them in order. Then it shows JFR, the most complete tool of the JDK, on an example: find the method that creates millions of objects. Which tool for which question Question Tool Command Cost Does the GC make long pauses? Does the heap after GC go up? GC logs -Xlog:gc*:file=gc.log keep it on in production Which area fills up, live? jstat jstat -gcutil <pid> 1s not given; its doc says “experimental and unsupported” How much heap is used? jcmd jcmd <pid> GC.heap_info medium Which class grows? jcmd jcmd <pid> GC.class_histogram high: runs a full GC What keeps the objects alive? heap dump + Eclipse MAT jcmd <pid> GC.heap_dump high: a big file Does the Metaspace grow? jcmd jcmd <pid> VM.metaspace medium What does native memory do? jcmd + NMT -XX:NativeMemoryTracking=summary, then jcmd <pid> VM.native_memory medium What do the threads do? jcmd jcmd <pid> Thread.print medium Which method allocates, where are the pauses, over time? JFR -XX:StartFlightRecording, then jfr view low with the default configuration The “medium” or “high” cost of the jcmd commands is the one given in their documentation. Each of these tools was already used in a post: GC logs, OutOfMemoryError, memory leaks and the heap dump with Eclipse MAT. ...

October 23, 2026 · 5 min

Java heap dump: find a memory leak with Eclipse MAT

In the post about memory leaks, two jcmd histograms showed which class grows. But not what keeps it alive. For that, you need a heap dump: a picture of the whole heap, with the objects and the links between them. We take the same leak again: UnboundedCache.java, a static HashMap cache that gets a new key on each request. We analyze it with Eclipse Memory Analyzer (MAT), an open source tool that Oracle’s guide names for heap dump analysis. All the commands are in the heap-dump folder of the java-gc-lab repository. ...

October 23, 2026 · 4 min

Java memory leaks: 6 classic cases, reproduced

In Java, the garbage collector frees the objects that nothing references anymore. So a memory leak is an object that is no longer useful but still referenced: the GC cannot free it. Oracle’s guide puts it this way: the application keeps references to objects “unintentionally”. Here are six classic leaks, each one reproduced by a small program of the public repository java-gc-lab, with what you see and the fix. What keeps an object alive The chain of references of a leak: a GC root, the static field AUDIT of the class StaticCollection, refers to an ArrayList, which refers to Order objects; they stay alive. A short-lived object that nothing refers to anymore is freed by the GC. What keeps an object alive every object reachable from a root stays alive GC root static AUDIT ArrayList the list of the field Order Order Order Order objects useless, but reachable stay alive: the leak short-lived object no reference left → freed by the GC The GC starts from “roots”: the static fields of the loaded classes, the local variables of the running threads… Every object that can be reached from a root stays alive. A leak is a path that someone forgot to cut. ...

October 23, 2026 · 6 min

Reading a Java GC log: every number explained

Turning on the GC log is easy. Reading it is harder: one G1 line holds about ten pieces of information, and the words change from one Java version to the next. This post reads real lines, written by three small programs of the public repository java-gc-lab: a normal load, very big objects, and a heap that is almost full. Turn on the log java -Xlog:gc*:file=gc.log:time,uptime,level,tags -jar app.jar gc*: all the GC messages (gc alone gives one line per GC); file=gc.log: in a file, with rotation built in (5 files of about 20 MB by default); time,uptime,level,tags: the “decorations” at the start of each line: the date and time, the time since the JVM started, the level and the tags. If you set nothing, the JVM uses uptime, level and tags. A pause line, with these decorations: ...

October 22, 2026 · 6 min

Java OutOfMemoryError: every message, reproduced

An OutOfMemoryError is not one single problem. The text after the colon tells you which memory area is full: the heap, the Metaspace, the direct memory or the threads. And each area is checked and fixed in a different way. For each message, I wrote a small program that causes it. They are in the public repository java-gc-lab, one file per message, to run with java without compiling first (Java 11 or later). ...

October 22, 2026 · 8 min

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