Hexagonal architecture with Spring Boot: a simple example

In a Spring Boot service organized by technical layers (controller, service, repository, entity…), the business rule ends up next to JPA, Kafka and Jackson code. To test it, you start Spring, or you mock a large part of the framework. This post shows another way to organize the code, the hexagonal architecture, on a small and complete example: a service that reads sensor readings from Kafka, checks them and computes statistics. The domain and the use cases are plain Java, Spring, Kafka and JPA stay in adapters, and a test makes the build fail if this rule is broken. The code is in the tag phase-1 of the public repository iot-monitoring-platform, presented in the post Kafka and Spring Boot: a complete local project. ...

October 24, 2026 · 9 min

Kafka and Spring Boot: a complete local project

One service receives the readings of sensors; another one must process and store them. If the first one calls the second one over REST, the two are tied: when the second one is stopped or slow, the first one cannot deliver anything. Kafka sits between them: the first one publishes a message, the second one reads it at its own pace. This post builds that link from end to end, locally: Kafka in KRaft mode in Docker, a Spring Boot service that publishes a plain line of text, another one that reads it, and a page that shows the partition and the offset of each message. All the code is in the tag phase-1 of the public repository iot-monitoring-platform. ...

October 24, 2026 · 10 min

AWS locally with Floci: an emulator, not a mock

My Java code stores files in S3 and data in DynamoDB. How do I develop and try it on my machine, without an AWS account, without a bill, and without changing the code that talks to AWS? This post introduces Floci, a local AWS emulator, with an end-to-end example: the AWS CLI creates the resources, a small Java application uses them, and the Floci web console shows them. I contribute to the Floci project. ...

October 24, 2026 · 6 min

Java dev machine: 8, 17 and 25 side by side with mise

A Java developer often works on several stacks at the same time: a legacy project in Java 8, a service in 17, a new project in 25. Maven here, Gradle there. Node for docs, Python for MkDocs. And around them, tools: aws, gh, kubectl, helm. Each SDK and each tool comes with its own installer. Little by little, the machine fills up: global versions that mix, sudo, a .zshrc filled by installers, an AWS variable left global. My question: how to have the right version of each SDK and each tool in each project, without installing anything as root, with one tool, and a terminal that stays fast? ...

October 24, 2026 · 9 min

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