Explain the roles of -XX:ArchiveClassesAtExit, -XX:SharedArchiveFile, and the .jsa file in a Spring Boot CDS setup.
answer
- .jsa = Java Shared Archive = parsed metadata
- ArchiveClassesAtExit = writer (training)
- SharedArchiveFile = reader (production)
- dynamic AppCDS = no pre-built class list
- metadata not bytecode -> JDK-coupled
basics
~20 sThe .jsa is the shared archive file holding pre-parsed class metadata. -XX:ArchiveClassesAtExit writes that archive when the training JVM exits. -XX:SharedArchiveFile points a later JVM at the archive to memory-map it at startup. One writes, one reads.
solid answer
~40 sThe **.jsa** (Java Shared Archive) is the file that stores the JVM's already-parsed, verified class metadata. Two flags bracket its lifecycle. **`-XX:ArchiveClassesAtExit=app.jsa`** is the *write* side: it enables JDK dynamic AppCDS, so the JVM records every class it loads during a run and dumps them into `app.jsa` at exit — this is what the Spring Boot training run uses (together with `-Dspring.context.exit=onRefresh` so the run exits cleanly after context refresh). **`-XX:SharedArchiveFile=app.jsa`** is the *read* side: it tells a later JVM to memory-map that archive at startup and reuse the metadata instead of re-parsing classes from disk — this is what production uses. So the mental model is: `ArchiveClassesAtExit` creates the archive during training; `SharedArchiveFile` consumes it during real runs. Using the wrong one (e.g., SharedArchiveFile during training) means no archive gets produced.
code
java · 10 lines// WRITE the archive (training run) — dynamic AppCDS:
// java -XX:ArchiveClassesAtExit=application.jsa \
// -Dspring.context.exit=onRefresh \
// -jar app/my-app.jar
//
// READ the archive (production run):
// java -XX:SharedArchiveFile=application.jsa -jar app/my-app.jar
//
// application.jsa = Java Shared Archive: the JVM's parsed,
// memory-mappable class metadata (not raw .class bytes).go deeper
Know one flag writes the archive and one reads it, and .jsa is the archive file.
Map ArchiveClassesAtExit->training/write and SharedArchiveFile->production/read, and know .jsa holds parsed metadata.
Explain dynamic vs static AppCDS and why the metadata format couples the archive to the JDK build.
Reason about archive layering (base + dynamic) and lifecycle management of the .jsa as a build artifact across the pipeline.
## The three things and how they relate ### The `.jsa` file `.jsa` stands for **Java Shared Archive**. It is a binary file containing the JVM's **internal, parsed-and-verified representation** of a set of classes (not the raw `.class` bytes). Because it's laid out for direct memory-mapping, at startup the JVM can `mmap` it read-only and use the class metadata immediately, skipping the read + parse + verify + build-metadata work for those classes. Being read-only and mappable, its pages can also be **shared across JVM processes** on the same host. ### `-XX:ArchiveClassesAtExit=app.jsa` — the writer This flag enables **dynamic AppCDS**. "Dynamic" means you don't have to pre-compute a class list: the JVM simply observes every class loaded during this run and, **when the JVM exits**, writes them all into the named archive. In the Spring Boot flow this is the **training run**: ``` java -XX:ArchiveClassesAtExit=application.jsa \ -Dspring.context.exit=onRefresh \ -jar app/my-app.jar ``` The `-Dspring.context.exit=onRefresh` companion property closes the Spring `ApplicationContext` right after refresh, so the process exercises the startup class-loading path and then **exits cleanly**, which is exactly when `ArchiveClassesAtExit` performs the dump. ### `-XX:SharedArchiveFile=app.jsa` — the reader This flag points a subsequent JVM launch at an existing archive to **use** it: ``` java -XX:SharedArchiveFile=application.jsa -jar app/my-app.jar ``` At startup the JVM validates the archive against the current classpath/JDK and, if valid, memory-maps it. This is the **production** run. ## Common confusions - **Write vs read:** `ArchiveClassesAtExit` **creates** the archive; `SharedArchiveFile` **consumes** it. They belong to different phases. Using `SharedArchiveFile` during training produces no new archive; using `ArchiveClassesAtExit` in production would needlessly re-dump at every exit. - **`.jsa` is metadata, not bytecode-in-a-jar.** It's the JVM's parsed form, which is why it's tied to a specific JDK build. - **Static vs dynamic AppCDS.** The older *static* approach required a two-step class-list dump (`-XX:DumpLoadedClassList` then `-Xshare:dump`). Dynamic AppCDS via `ArchiveClassesAtExit` collapses that into one run and is what Spring Boot's documented flow uses. ## Extra: combining the base and dynamic archives A dynamic archive built with `ArchiveClassesAtExit` layers on top of the JDK's default base archive, so at runtime you effectively get JDK classes (base) plus your app/library classes (dynamic) shared together.
- Does .jsa store the raw .class bytecode?No — it stores the JVM's internal parsed and verified representation of the classes, laid out for direct memory-mapping. That's why the archive is coupled to the specific JDK build that produced it.
- What's the difference between static and dynamic AppCDS?Static AppCDS needs a pre-computed class list (-XX:DumpLoadedClassList then -Xshare:dump). Dynamic AppCDS (-XX:ArchiveClassesAtExit) records loaded classes automatically and dumps at JVM exit — a single-run flow, which is what Spring Boot uses.
saying these in an interview costs you the question
- Swapping the roles: thinking SharedArchiveFile creates the archive or ArchiveClassesAtExit reads it.
- Believing the .jsa contains raw bytecode rather than parsed JVM metadata.
- Using both flags simultaneously and expecting a coherent create-then-use in one run.