How to use AppCDS with Spring Boot

Transcript 


In this video, I will show you how to use Application Class Data Sharing (AppCDS) with Spring Boot applications. AppCDS is a JVM feature that reads and parses a set of system classes and application classes, stores the data in an archive, and then reads the data from the archive upon startup, resulting in faster application startups. AppCDS is compatible with all applications and doesn’t require any code changes. Additionally, using AppCDS with Ahead-of-Time (AOT) processing, supported by Spring, further reduces startup time. We will explore how to use AppCDS and AOT processing on a local machine and in containers by dockerizing our application using Dockerfiles and Buildpacks.

For this tutorial, you will need a Spring Boot application. I’ll use the Spring Petclinic application, available on GitHub. You will also need Docker, so make sure the engine is up and running. Let's begin by creating an archive on a local machine. While no application code changes are required, enabling AOT processing in the Maven plugin configuration is necessary. Using Liberica JDK 23 and Spring Boot version 3.3 or later, we start by creating an executable JAR file using the maven clean package command. Running the application with a standard java -jar command initially takes almost four seconds to start.

Next, we create a CDS archive. Instead of using the executable JAR directly, the Spring team recommends unpacking it into an exploded JAR for production. After extracting it, we use options like -Dspring.aot.enabled and ArchiveClassesAtExit to create the archive. The Dsprint.context.exit=onRefresh option ensures the application exits automatically after startup. While some older classes may not be archived, most are included. Once the archive is created, running the application with the SharedArchiveFile option results in a startup time of less than two seconds, a 40% improvement.

To enable AppCDS in a container, we use a Dockerfile. The first stage employs the Liberica Runtime Container with LibericaJDK Lite and Alpaquita Linux to build the project. The second stage extracts the JAR into layers, optimizing image updates. Finally, the container is built using Liberica Runtime Container with a prepackaged AppCDS archive. Using options like -Dspring.aot.enabled and ArchiveClassesAtExit, we create the archive during the build process. The resulting container image is 287MB and starts in under three seconds.

We also demonstrate using Buildpacks to build a container image with AppCDS and AOT enabled. Buildpacks automatically create layered JARs and can be configured by adding environment variables like BP_SPRING_AOT_ENABLED and BP_JVM_CDS_ENABLED to the Maven plugin. While Buildpacks produce slightly larger images (e.g., 538MB), they simplify the process. Running the Buildpack-based container shows startup times of just over two seconds, confirming that AppCDS and AOT are working as expected.

In this video, we explored using AppCDS and AOT processing with Spring Boot applications. Don't forget to like, subscribe, and see you next time!

Summary

This tutorial demonstrates how to use Application Class Data Sharing (AppCDS) and Ahead-of-Time (AOT) processing with Spring Boot applications to reduce startup time by 40–50%. AppCDS creates an archive of parsed classes for faster loading, requiring no code changes, and works both locally and in containers. The tutorial covers building optimized Docker images using Dockerfiles or Buildpacks for efficient deployment and improved performance.

About Catherine

Java developer passionate about Spring Boot. Writer. Developer Advocate at BellSoft

Social Media

Tags

Videos
card image
Mar 9, 2026
jOOQ Deep Dive: CTE, MULTISET, and SQL Pipelines

Some backend developers reach the point where the ORM stops being helpful. Complex joins, nested result graphs, or CTE pipelines quickly push frameworks like Hibernate to their limits. And when that happens, teams often end up writing fragile raw SQL strings or fighting performance issues like the classic N+1 query problem. In this video, we build a healthcare scheduling application NeonCare using jOOQ, Spring Boot 4, and PostgreSQL, and show how to write production-grade SQL directly in Java while keeping full compile-time type safety.

Videos
card image
Feb 27, 2026
Spring Developer Roadmap 2026: What You Need to Know

Spring Boot is powerful. But knowing the framework isn’t the same as understanding backend engineering. In this video, I walk through the roadmap I believe matters for a Spring developer in 2026. We start with data. That means real SQL — CTEs, window functions, normalization trade-offs — and understanding what ACID and BASE actually imply for system guarantees. Spring Data JPA is useful, but you still need to know what happens underneath. Then architecture: microservices vs modular monolith, serverless, CQRS, and when HTTP, gRPC, Kafka, or WebSockets make sense. Not as buzzwords — but as design choices with trade-offs. Security and infrastructure follow: OWASP Top 10, AuthN vs AuthZ, encryption in transit and at rest, Docker, Kubernetes, Infrastructure as Code, and observability with Micrometer, OpenTelemetry, and Grafana. This roadmap isn’t about mastering every tool. It’s about knowing what affects reliability in production.

Further watching

Videos
card image
Apr 2, 2026
Java Memory Options You Need in Production

JVM memory tuning can be tricky. Teams increase -Xmx and assume the problem is solved. Then the app still hits OOM. Because maximum heap size is not the only thing that affects memory footprint. The JVM uses RAM for much more than heap: metaspace, thread stacks, JIT/code cache, direct buffers, and native allocations. That’s why your process can run out of memory while heap still looks “fine”. In this video, we break down how JVM memory actually works and how to control it with a minimal, production-safe set of flags. We cover heap sizing (-Xms, -Xmx), dynamic resizing, direct memory (-XX:MaxDirectMemorySize), and total RAM limits (-XX:MaxRAMPercentage) — especially in containerized environments like Docker and Kubernetes. We also explain GC choices such as G1, ZGC, and Shenandoah, when defaults are enough, and why GC logging (-Xlog:gc*) is mandatory before tuning. Finally, we show how to diagnose failures with heap dumps and OOM hooks. This is not about adding more flags. It’s about understanding what actually consumes memory — and making decisions you can justify in production.

Videos
card image
Mar 26, 2026
Java Developer Roadmap 2026: From Basics to Production

Most Java roadmaps teach tools. This one teaches order — the only thing that actually gets you to production. You don’t need to learn everything. You need to learn the right things, in the right sequence. In this video, we break down a practical Java developer roadmap for 2026 — from syntax and OOP to Spring, databases, testing, and deployment. Structured into 8 levels, it shows how real engineers grow from fundamentals to production-ready systems. We cover what to learn and what to ignore: core Java, collections, streams, build tools, Git, SQL and JDBC before Hibernate, the Spring ecosystem, testing with JUnit, and deployment with Docker and CI/CD. You’ll also understand why most developers get stuck — jumping into frameworks too early, skipping SQL, or treating tools as knowledge. This roadmap gives you a clear path into real-world Java development — with priorities, trade-offs, and production context.

Videos
card image
Mar 19, 2026
TOP-5 Lightweight Linux Distributions for Containers

In this video, we compare five lightweight Linux distributions commonly used as base images: Alpine, Alpaquita, Chiseled Ubuntu, RHEL UBI Micro, and Wolfi. There are no rankings or recommendations — just a structured look at how these distros differ so you can evaluate them in your own context.