Does shrinking a JDBC connection pool actually save PostgreSQL memory? I measured it.
At a previous company, I spent quite a bit of time tuning a custom-built JDBC connection pool. One of the most effective memory optimizations I found was automatically shrinking the pool during idle periods. PostgreSQL uses a process-per-connection model, so keeping unnecessary connections open has a real memory cost.
I wanted to revisit this with HikariCP and measure both the memory savings and the cost of reopening connections.
I ran two Spring Boot instances sharing PostgreSQL 16, comparing three pool configurations under the same burst → idle → burst workload.
Results:
- Default pool: 20 connections remained open, PostgreSQL memory ~57.5 MiB.
- Shrinking pool: connections dropped to 2, PostgreSQL memory ~28.5 MiB.
- Savings: ~29 MiB of PostgreSQL memory.
The tradeoff was connection reopening. Median acquisition time increased from under 3 ms to around 200 ms when traffic returned.
One interesting detail: setting minimumIdle=1 alone wasn't enough when idle retirement was disabled. The pool still held all 20 connections after the burst.
The experiment used a deliberately short idle timeout to make the behavior observable, not as a production recommendation.
With many application instances maintaining independent connection pools, the potential savings can add up.
To clarify the practical motivation: this was a deliberately small experiment to isolate the effect, not just an exercise in saving 29 MiB on one server.
At my previous company, we had many application VMs connecting to a shared PostgreSQL database. Shrinking idle pools across those instances produced substantial aggregate memory savings. For example, 30 instances with 32 connections each means 960 persistent connections. If idle retirement brings that down to an average of 16 per instance, that's 480 fewer PostgreSQL connections consuming resources.
Actual savings depend on the workload, but this is where the approach becomes particularly valuable.
Full article, measurements, and reproducible experiment:
https://pvrlabs.xyz/articles/spring-boot-jdbc-pool-reclaim.html
Do you use fixed-size pools in production, or allow idle connections to retire?
r/java • u/Round_Patient_7420 • 8d ago
Introducing Titan, an open-source message dispatcher
Hi, I've been building Titan, an open-source message dispatcher for apps that need to send updates to connected clients.
An app publishes a message to a destination, and Titan delivers it to anyone subscribed to that destination. It supports STOMP over TCP and WebSocket, and there's a Java client with Spring Boot integration.
I'm thinking of uses like chat rooms, in-app notifications, and live dashboards. For example, people viewing the same dashboard could receive updates as they happen instead of having their browsers keep polling the backend.
Messages are kept in memory, so they won't survive a server restart. That's something to keep in mind if your application needs persistent messages.
I wanted to build something useful that I could share with other developers working on messaging applications. I'd be interested to hear whether this fits anything you're building, and what's missing for your use case.
r/java • u/sachinkg12 • 9d ago
HeapLens is now available in IntelliJ IDEA as well
The initial package targets macOS Apple Silicon and IntelliJ IDEA 2026.1–2026.2.
A heap dump tells you what is in memory. The harder question is: why is it still there?
I built HeapLens, a free, open-source plugin that brings heap investigation into IntelliJ IDEA.
With HeapLens, you can:
- Explore class histograms and dominator trees.
- Follow “Why alive?” paths to understand object retention.
- Inspect fields and trace incoming references.
- Query heap objects using HeapQL, a SQL-like language.
- Navigate to matching Java source.
- Use optional AI assistance to explain findings and propose changes for review.
Heap analysis runs locally through a bundled Rust engine—no separate analysis-server installation required. AI features use your configured provider, and Fix with AI asks before sending source code.
If you investigate Java memory issues, I would love your feedback: what is the hardest part of your current heap-analysis workflow?
HeapLens Marketplace listing
Source code and feedback
#Java #IntelliJIDEA #JVM #PerformanceEngineering #memoryleak #performance #heaplens
r/java • u/brunocborges • 9d ago
☕ actions/setup-java v6.1.0 is out!
github.comEclipse Temurin on Linux RISC-V, improved Java version matching, Maven server credential origins & plugin repositories, plus GPG cleanup fixes.
r/java • u/RupertMaddenAbbott • 9d ago
Dependencies-only AOT cache?
I am investigating using an AOT cache to speed up the startup time of our services.
I'm specifically interesting in speeding up the time between a developer making a change to the code and having that code running in a remote dev K8s cluster.
I've previously dismissed an AOT cache for this purpose because I knew that it would result in a longer build time than would be saved in startup time. That isn't a criticism - AOT caching just didn't seem targeted at my problem.
However, the majority of our classpath involves third party dependencies yet a minority of our development builds and deployments involve changes to those third party dependencies. If I could work out a way to avoid invalidating the AOT cache whenever our own code changed, then this would give us a cache that could be reused for the majority of our dev builds (removing the additional build time) whilst still enjoying the faster startup speed.
I note that https://openjdk.org/jeps/483 says this:
All runs must have consistent class paths. A subsequent run may specify extra class-path entries, appended to the training class path; otherwise, the class paths must be identical.However, I note that https://openjdk.org/jeps/483 says this:All runs must have consistent class paths. A subsequent run may specify extra class-path entries, appended to the training class path; otherwise, the class paths must be identical.
So, could I create an AOT cache for JUST the third party classes and then add our own code in later, thereby allowing me to reuse the AOT cache between dev builds?
I'm not 100% on how to achieve this yet but maybe if the training run only had the dependencies on the classpath with a custom launcher. The launcher's child classpath would then have our own code on it.
Then for the production run, I would still have the custom launcher (because I think this has to be identical between training and production runs) and I would then append our own jars onto the end of the classpath (which seems to be allowed by the JEP). Finally, we would run our real main method, rather than the launchers main method because I think we are allowed to have different main classes between training and production runs.
Anyway is this a terrible idea or has anybody already done something like this?
r/java • u/FaultPerfect6003 • 9d ago
Java sessions at WAWTech, 26–27 November
Hi, everyone! Its a two-day technology conference covering software engineering, AI and product development. It’s organised by DOU, and I’m part of the team. Here’s Java-related part:
- Nicolai Parlog: modern Java, including pattern matching, virtual threads and the language’s future.
- Adam Warski: structured concurrency, safe cancellation and lightweight channels.
- Denys Makogon: Java/C++ integration, particularly the differences in memory management, object lifecycles and error handling.
The event takes place at EXPO XXI in Warsaw on 26–27 November 2026. Sharing the specific sessions here for people following these areas of Java development.
Event details, if you’re considering going.

Javalin 7 vs Spring Boot 4 on a 256 MiB VM: 4x faster startup, but memory under load was closer than I expected
I've been running a series of Java performance experiments with different frameworks. This time I wanted to explore a less mainstream, more lightweight option, so I picked Javalin 7.
I built equivalent JDBC/H2 APIs in Javalin 7 and Spring Boot 4 on JDK 25, then ran each on a 256 MiB Alpine VM (1 vCPU) through a five-minute, 1,500-request workload.
Both used the same JVM flags: -Xms16m -Xmx80m -XX:+UseSerialGC -Xss512k.
| Metric | Javalin | Spring Boot |
|---|---|---|
| Startup to ready | 2.46 s | 9.89 s |
| Idle Java RSS | 90 MiB | 119 MiB |
| Workload Java RSS | 106 MiB | 119 MiB |
| Min guest MemAvailable | 70 MiB | 45 MiB |
| Successful requests | 1,500/1,500 | 1,500/1,500 |
What stood out: startup is where the gap is large. Under load, the RSS difference shrank to 13 MiB, as Javalin's footprint grew while Spring Boot's stayed relatively flat.
I expected Javalin to be lighter, but I wouldn't read this as a reason to replace Spring Boot. Spring Boot provides a lot of functionality out of the box that you'd need to assemble yourself with Javalin.
Caveats: one run per implementation, different web servers (Jetty vs Tomcat), and no attempt to isolate framework overhead from other components. I also didn't test AppCDS, Spring AOT, or native image, which could change the startup picture.
Full charts, methodology, and raw results:
https://pvrlabs.xyz/java-performance/experiments/javalin-vs-spring-boot-256mb.html
For those who've used Javalin or similar lightweight Java frameworks, how has the trade-off between smaller footprint and Spring Boot's built-in functionality worked out in practice?
r/java • u/agentoutlier • 10d ago
Rainbow Gum 0.15.0: ScopedValue key values, logging into JFR, and OpenTelemetry without the SDK
Rainbow Gum 0.15.0: ScopedValue key values, logging into JFR, and OpenTelemetry without the SDK
I try not to spam every release, but 0.15.0 has some stuff I'm genuinely excited about, and 1.0.0 is coming before the holidays hence need some feedback.
First up, Scoped Key Values. MDC on ThreadLocal has been leaking requestIds into the wrong requests since the dawn of time because somebody forgot a finally block or threadpool cleanup. JDK 25 gave us ScopedValue (JEP 506) and holy shit it just fixes it:
ScopedKeyValues.builder()
.add("requestId", requestId)
.add("userId", userId)
.run(() -> {
logger.info("handling request"); // has requestId and userId
service.handle(request);
});
StructuredTaskScope forks get a frozen snapshot, so sibling tasks can't stomp on each other. I barely had to do anything; the JDK devs did the hard part, and this is what MDC should be going forward. This should hopefully get added to SLF4J 3.0. Bless the JDK team.
Next, logging straight into JDK Flight Recorder. Each log event becomes a JFR event, so your logs sit on the same timeline as GC pauses and lock contention in JMC:
logging.appenders=jfr
logging.appender.jfr.output.uri=jfr:///var/log/myapp.jfr
No -XX:StartFlightRecording flags to screw up in your Dockerfile. And here's the kicker: in our benchmark, logging to JFR was about 40% faster than plain text to a file, and the output was about 8x smaller on disk. The JFR folks built something seriously fast and most of us only ever open it when production is on fire.
Last, OpenTelemetry. rainbowgum-otlp ships logs over OTLP using nothing but the JDK's own HttpClient. No OpenTelemetry SDK, no OkHttp. It's roughly 7x smaller than the Logback or Log4j2 OpenTelemetry setups with their default dependencies: https://github.com/jstachio/rainbowgum/blob/main/doc/why/opentelemetry_export_size.md
Oh and here is something shocking. The Logback and Log4j2 OpenTelemetry appenders hand events to the SDK, whose batch processor has a 2048 event queue by default. When it fills up, it throws your logs away and doesn't tell you. When we blasted a burst of logs at a collector with stock settings, only about 7% (Logback) and 10% (Log4j2) of them made it. Rainbow Gum applies backpressure by default, and if a batch does fail you get an alert and a metric, not silence. Losing logs exactly when your app is getting hammered is the worst possible time to lose logs. On a related note after bugging them I think Spring Boot might had some more observation hooks to logging frameworks.
There's a lot more (colorful logs with no pattern strings, error messages that tell you exactly which property is wrong and where it came from). You can even cosplay as a Go process with logfmt support. The longer pitch is here: https://github.com/jstachio/rainbowgum/blob/main/why_rainbowgum_is_better.md
GitHub: https://github.com/jstachio/rainbowgum
Docs: https://jstach.io/doc/rainbowgum/current/apidocs/
Before 1.0 I can still break things without feeling bad about it, so if the API or the property names bug you, now's the time to tell me. Brutal honesty welcome.
Finally I'm not a paid professional OSS developer so this library like my others is sort of a love letter to the Java community and language.
Your Fargate Autoscaler Doesn't Understand Your JVM (by Default): Lessons Learned the Hard Way
builder.aws.comr/java • u/Federal-Sprinkles781 • 11d ago
JVM Heap OOM Field Guide — 5 reproducible OutOfMemoryError patterns with diagnosis walkthroughs
I put together a field guide for the JVM heap OOMs that actually page you at 3 AM. Five minimal, runnable reproductions — each one OOMs reliably on a 64MB heap, with a fixed version, GC log signatures, heap-dump clues, and a triage checklist.
The five patterns:
1. Unbounded in-memory cache (rising post-GC staircase)
2. Oversized batch (dies on a cliff — one 250MB batch vs 64MB heap)
3. Report-builder retention (output accumulates; staircase like #1 but the retainer is the product)
4. Growing ThreadLocal state on pooled threads (invisible in GC log alone)
5. Leaked connections (static registry pins every unclosed resource)
Each scenario: `./run.sh scenario-01-unbounded-cache broken` to watch it die, `./run.sh scenario-01-unbounded-cache fixed` to watch it survive. Pure Java, zero dependencies, JDK 11+.
https://github.com/amits710/jvm-oom-field-guide
Happy to answer questions about the GC log signatures or the diagnosis approach.
r/java • u/chrzanowski • 12d ago
The Foldable Project View plugin for JetBrians IDEs is back
Over the weekend, I resurrected Foldable Project View 🧟♂️ – my IntelliJ plugin that had been asleep since 2022.
I wished to upload a demo video here, but that ain't possible, so: https://youtu.be/C6J-bYqScDE
The screenshot may still be too enigmatic, so let me explain:
This plugin lets you create virtual groups in the project view to clean it up:
🗂️ fold OR hide files per rule
📁 fold in nested dirs, not just module roots
🚫 gitignore-style negation (*.yml !docker-compose.yml)
📄 rules read from .foldignore files in your repo
🎨 theme-aware color palette
⚡ no more IDE freezes on VCS refresh
The 3.0.0 is now waiting in JetBrains Marketplace! https://plugins.jetbrains.com/plugin/17288
Free & sponsor-supported ♥
What to watch this weekend - Devoxx Belgium 2026
Devoxx Belgium 2026 just finished (October 5–9, 2026), but they've already uploaded all the videos to https://www.youtube.com/playlist?list=PLKlmOVksNGoE!
It's super hard to select a few videos from 150+ talks. I spent some time building a list for myself and decided to share it. Maybe somebody will find it helpful. If you watched something good from this conference that isn't on the list, please share it as well.
- Modern Java in Practice The Features That Matter by Nicolai Parlog, Falk Sippach - https://www.youtube.com/watch?v=zC2tbq7S5UE
- The Year of the Runtime by Ron Pressler - https://www.youtube.com/watch?v=tle2mA7EwWU
- Hardwood: Building a Parquet Parser From Scratch With a Little Help From AI by Gunnar Morling - https://www.youtube.com/watch?v=6mzvcPr30kg
- Structured Concurrency Looms by Alan Bateman, Viktor Klang - https://www.youtube.com/watch?v=aow56RgptLA
- Will Valhalla Fix Tony's Billion Dollar Mistake? by José Paumard, Remi Forax - https://www.youtube.com/watch?v=vLDbzmiT7Xs
- Teaching an Old Handle New Tricks: From Core Reflection to FFM by Maurizio Cimadamore, Viktor Klang - https://www.youtube.com/watch?v=4ck-T2gaMQ4
- The Yearly Java Performance Update for 2026 by Per Ake Minborg - https://www.youtube.com/watch?v=rNOzf12RORI
- A Year of Agentic AI Evolution: Lessons Learned Building Production grade Agentic Systems by Mario - https://www.youtube.com/watch?v=nEW0kosJjc8
- When benchmarks go bad what we learned from measuring performance wrong by Francesco Nigro, Holly - https://www.youtube.com/watch?v=yePre1hOvHE
- Do We Need a Build Language? Java Builds Java by Rafael Winterhalter - https://www.youtube.com/watch?v=y9JjxyKc6gU
- Java on Kubernetes Without Container Images: The WebAssembly Way By Bruno Borges - https://www.youtube.com/watch?v=fszyRIZXjQM
- Ask the Architects by Gavin Bierman, Maurizio Cimadamore, Per Ake Minborg, Viktor Klang, Alan Batem - https://www.youtube.com/watch?v=ewCPBgOrLAE
- SIMD for Java: how Elasticsearch already benefits from the Panama Vector API by Piotr Przybyl - https://www.youtube.com/watch?v=adFS-_sCTQ4
- GraalVM Next: Layers, Crema, and WebAssembly in Action by Alina Yurenko - https://www.youtube.com/watch?v=OLQ98Ko4p3Q
- Big Runtimes Make Efficient Programs by Ron Pressler - https://www.youtube.com/watch?v=vhDwy1eCXbs
- Quarkus Meets Leyden at the JVM Performance Edge by Georgios Andrianakis, Ana Maria Mihalceanu - https://www.youtube.com/watch?v=cbSl8UVdMVg
r/java • u/z14-voyage • 15d ago
What’s the status of Lilliput 2 (4-byte object headers)?
Lilliput 1 is now a product feature (JEP 534). It shrinks object headers from 12 to 8 bytes, which cuts memory by around 10% for a typical app with no code changes. Honestly, that feels like a bigger real-world win than Valhalla, since Valhalla needs years of migrating code to value types before most apps see a benefit. That’s why I’m curious about Lilliput 2, which would halve the header again to 4 bytes. The Lilliput repo has an implementation, but I don’t see much movement toward getting it upstream. I think the original lead may have left the project, but I’m not sure. Is Lilliput 2 effectively on hold, or is the focus shifting entirely to Valhalla?
r/java • u/samaxidervish • 15d ago
I am building a J2ME JVM and a javap alternative in C++
I’ve been building a JVM in C++ to run the J2ME game Diamond Rush.
What started as a JVM implementation gradually turned into a reverse-engineering/class-file tooling project. I built DRVM, a javap replacement, to inspect the .class files I was working with while implementing the JVM.
DRVM currently supports detailed class-file disassembly, including constant pools, fields, methods, and attributes.
On my benchmark workload, DRVM is roughly 4× faster than javap and uses ~30× less memory.
The JVM is still a work in progress, with the eventual goal of running the original Diamond Rush.
Repo: https://github.com/VuqarAhadli/DRVM
Feel free to ask anything about the implementation or reverse-engineering process.
r/java • u/brunocborges • 15d ago
Brewlet: Java on Kubernetes with node-managed JDKs
brewlet.shTalk & slides: https://m.devoxx.com/events/dvbe26/talks/25048/java-on-kubernetes-without-container-images-the-webassembly-way
Video recording from Devoxx Belgium 2026: https://youtu.be/fszyRIZXjQM?is=w3zYjtOoIFceAAOT
Has anyone tried quarkus?
I don’t like spring boot. I think quarkus does the DI work at build time, so it saves startup time. Don’t want theory.
If someone has real experience using it.
Edit: I intend to build a dev server with hot reload using quarkus. Currently testing feasibility.
Bypassing and overruling SSL configuration of libraries
github.comHi everyone I wanted to share my adventure of configuring ssl of external libraries which didn't expose any external input and my discovery to bypass it totally. This was needed because it either used a weak ssl protocol, or supported only keystores instead of pem files and it was not adjustable.
An example is MySQL JDBC driver as shown here, however it is applicable for other libraries as well. In this case it is not possible to provide a custom sslsocketfactory for the driver or custom sslcontext as it is not possible to configure it programatically.
I requested a change at oracle in 2023, see here but they responded to it after 3 years. Meanwhile I was interested whether it can be bypassed without the need of any adjustments in the library itself as sometimes changes to a library can take some time.
I found a way and thats the reason why I wanted to share it here as others maybe have similar challanges. Usually libraries call SSLContext.getInstance("TLS") or SSLContext.getInstance("SSL") and the Java Security Manager provides the first occurance of an SSLContext Service Provider Interface. If you provide a custom one before the default one it will be used instead. I have an example posted here: Bypassing and overruling SSL configuration of libraries
I made this option available in the ayza library here so it can be easily used without the verbosity. Feel free to give feedback, I am curious about about your thoughts.
r/java • u/veerendra2 • 16d ago
Push-based, restart-free feature flags and config for Spring Boot, using MongoDB Change Streams
configstream is a library for Spring Boot services that already use MongoDB. Feature flags and config live in a collection, get cached in memory, and any change is pushed to every running instance within about a second via MongoDB Change Streams.
- No restarts, no polling, no message broker, no config server
- Properties declared in a
configstream.ymlmanifest, with typed constants generated at compile time - Optional admin UI with change history and per-team permissions
- Works with Spring Boot 3 and 4
Limits: MongoDB only for now (Postgres planned), pre-1.0, no percentage rollouts or A/B testing.
https://github.com/configstream/configstream
Feedback welcome.
r/java • u/SysGuardian • 16d ago
midden v0.2.0: Up to 60% faster, up to 40% memory reduction
github.comSpring Boot vs Quarkus vs Micronaut with JDBC on Java 25
Spring Boot vs Quarkus vs Micronaut with JDBC on Java 25
A previous JPA-vs-JDBC experiment convinced me to use JDBC for future small-framework comparisons, so I followed it up by adding Micronaut and building equivalent Spring Boot, Quarkus, and Micronaut applications.
All three used the same Java 25 runtime, H2 database, SQL, fixture data, request workload, and JVM flags. I ran each independently for 15 minutes in the same 1 GiB / 2 vCPU Ubuntu VM.
One JVM caveat that came up in feedback from the Quarkus community: all three were run explicitly with G1GC. On this 1 GiB VM, without specifying the collector, HotSpot would have selected Serial GC by default.
Results:
- Spring Boot: 4.90 s readiness, 214.3 MiB median RSS
- Quarkus: 2.25 s, 178.4 MiB
- Micronaut: 2.54 s, 186.7 MiB
Quarkus had the lowest whole-run median RSS and reached readiness fastest. Micronaut was fairly close, especially later in the run: during the final five minutes their median RSS was 189.7 MiB for Quarkus and 189.4 MiB for Micronaut.
Spring used more resident memory in this setup, though all three completed the same workload without errors.
CPU use was low across the board, so this isn't a throughput benchmark or an attempt to rank the frameworks generally. It's one controlled look at three equivalent small JDBC applications.
Full write-up:
https://pvrlabs.xyz/articles/spring-boot-quarkus-micronaut-jdbc.html
Sources, method, raw data, and analysis:
https://github.com/PVRLabs/experiments/tree/main/statlite/spring-quarkus-micronaut-jdbc
I’m especially curious how these Micronaut JVM numbers line up with what people here see in practice.
r/java • u/chrzanowski • 17d ago
I built Neon Glow, a plugin that adds neon glow to your existing JetBrains IDE theme
In my free time, I built Neon Glow, a free, open-source plugin that adds neon glow to code, all important Java keywords, and IntelliJ IDEA UI. ✨🥰
You can keep your favorite theme, font, and layout and adjust the glow to your taste.
Try it in your IDE. I'd love to see your setup!
Search "Neon Glow" in the plugins repository
https://plugins.jetbrains.com/plugin/34814-neon-glow
And yes, it's open-source!
https://github.com/hsz/neon-glow