What does the spring-boot-maven-plugin's repackage goal do, and what is a layered jar?
answer
- repackage = thin jar -> executable fat jar
- BOOT-INF/classes + BOOT-INF/lib (nested jars)
- JarLauncher, not shading
- .original = old thin jar
- layers.idx ordered by change frequency for Docker cache
basics
~20 sThe repackage goal takes the plain jar Maven built and rewrites it into an executable fat jar that embeds all dependencies and a launcher, so you can run it with java -jar. A layered jar splits it into layers ordered by change frequency to make Docker image builds cache better.
solid answer
~40 sspring-boot-maven-plugin:repackage runs in the package phase after maven-jar-plugin. It takes the thin jar and produces an executable 'fat' (uber) jar: it nests your dependency jars under BOOT-INF/lib, your classes under BOOT-INF/classes, and adds Spring Boot's JarLauncher plus a Main-Class/Start-Class manifest so java -jar works without a container. It uses a special nested-jar classloader rather than shading classes together, avoiding class collisions. The original thin jar is renamed with a .original classifier. Layered jars (layertools/extract) split BOOT-INF into ordered layers — dependencies, spring-boot-loader, snapshot-dependencies, application — so that in a Dockerfile each layer becomes its own image layer; since your application code changes far more often than libraries, Docker reuses the cached dependency layers and rebuilds are smaller and faster.
code
bash · 4 linesmvn package
java -jar target/app-1.0.0.jar
# layered extraction for Docker layer caching:
java -Djarmode=layertools -jar target/app-1.0.0.jar extractgo deeper
Know java -jar works because repackage embeds dependencies and a launcher.
Explain BOOT-INF layout, the JarLauncher manifest, and the .original artifact.
Contrast nested-jar classloading with shading and justify layered jars for image caching.
Standardize layered-jar + Docker-cache strategy (or buildpacks/native-image) across services for build performance and supply-chain hygiene.
## The problem repackage solves A normal `mvn package` for a Spring Boot app produces a thin jar containing only your classes — it cannot run standalone because its dependencies are elsewhere. The **`spring-boot-maven-plugin`** adds a `repackage` goal, bound to the `package` phase, that runs **after** `maven-jar-plugin` and rewrites that thin jar into an **executable fat (uber) jar**. ## What the fat jar looks like The repackaged jar has a special internal layout: - `BOOT-INF/classes/` — your application classes. - `BOOT-INF/lib/` — your dependency jars, kept **whole** (nested jars). - `org/springframework/boot/loader/...` — the Spring Boot **loader** classes. - `META-INF/MANIFEST.MF` with `Main-Class: org.springframework.boot.loader.launch.JarLauncher` and `Start-Class: your.App`. Key detail: Spring Boot does **not** shade/merge dependency classes. It keeps each dependency as a nested jar and uses a custom classloader to read jars-within-a-jar. This avoids the class-overwrite and resource-merge problems of shading. The original thin jar is preserved as `app-1.0.0.jar.original`. Now `java -jar app.jar` just works. ## Layered jars With `<layers><enabled>true</enabled></layers>`, the jar's `BOOT-INF` is organized into named **layers** recorded in `layers.idx`, ordered least- to most-frequently-changing: 1. `dependencies` (released libs) 2. `spring-boot-loader` 3. `snapshot-dependencies` 4. `application` (your code) You extract them with `java -Djarmode=layertools -jar app.jar extract` (or the newer `tools extract`). In a Dockerfile each extracted layer is `COPY`-ed separately, becoming its own image layer. Because Docker caches layers by content and your **application** layer changes far more often than the **dependencies** layer, rebuilds reuse the cached dependency layers — dramatically smaller, faster image pushes. ```xml <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <layers><enabled>true</enabled></layers> </configuration> <executions> <execution><goals><goal>repackage</goal></goals></execution> </executions> </plugin> ``` ```bash mvn -DskipTests package java -jar target/app-1.0.0.jar # inspect/extract layers: java -Djarmode=layertools -jar target/app-1.0.0.jar extract ``` ## war option Spring Boot can also repackage a `war` so it is **both** deployable to a container **and** executable via `java -jar` — handy when you must keep app-server compatibility.
- How is Spring Boot's fat jar different from a shade-plugin uber jar?shade merges all dependency classes into one flat namespace (risking class/resource collisions and broken signed jars); Spring Boot nests whole dependency jars under BOOT-INF/lib and uses a custom nested-jar classloader, avoiding those collisions.
- Why order layers by change frequency?Docker caches image layers by content. Putting rarely-changing dependencies in an early layer and frequently-changing app code last lets rebuilds reuse cached dependency layers, shrinking build and push time.
saying these in an interview costs you the question
- Saying repackage shades/merges classes like maven-shade
- Forgetting the repackage execution is needed for an executable jar
- Claiming layered jars change runtime behavior rather than just Docker caching