Caching & Performance
jbundle uses a layered caching system to optimize both build time and runtime performance.
How Caching Works
The output binary contains independent layers:
[stub script] [runtime.tar.gz] [app.jar.gz] [crac.tar.gz?]Each layer is cached by content hash at ~/.jbundle/cache/:
~/.jbundle/cache/
├── jdk-21-linux-x64/ # Downloaded JDK (reused across builds)
├── rt-abc123/ # Extracted runtime
├── app-def456/ # Extracted app + app.jsa
└── crac-ghi789/ # CRaC checkpoint (if enabled)Why This Matters
Build time: Changing only application code doesn't re-download the JDK or re-create the runtime.
Run time: Updating your app doesn't re-extract the runtime layer. Only the app layer is replaced.
CI/CD: Multiple builds with the same JDK version share the cached download.
Startup Performance
First Run vs Subsequent Runs
What happens
Extract layers + generate AppCDS
Load from cache
Overhead
+2-5s
None
Startup (cli)
~800-1500ms
~200-350ms
Startup (server)
~1000-2000ms
~400-600ms
Why First Run is Slower
Extraction — Compressed layers are decompressed to cache
AppCDS generation — JVM creates
.jsafile with pre-processed classes
This is a one-time cost per app version.
Why Subsequent Runs are Faster
Cache hit — Everything already extracted
AppCDS loaded — JVM skips parsing and verification
Profile flags — Optimized JVM configuration
AppCDS (Class Data Sharing)
Enabled by default on JDK 19+. The JVM automatically generates a shared archive on first run:
This file contains:
Pre-parsed class metadata
Pre-verified bytecode
Pre-computed class layouts
Result: 60-75% faster startup on subsequent runs.
Disabling AppCDS
Useful if you observe issues with specific libraries.
CRaC (Coordinated Restore at Checkpoint)
Optional feature for near-instant startup (~10-50ms).
How It Works
Application starts and warms up
Checkpoint is created (memory snapshot)
Checkpoint is bundled in the binary
Subsequent runs restore from checkpoint
Requirements
Linux only
JDK with CRaC support (e.g., Azul Zulu with CRaC)
Usage
Falls back to AppCDS if restore fails.
Cache Management
View Cache Info
Shows cached JDKs, runtimes, and apps.
Clean Cache
Removes all cached data.
Binary Size Optimization
jbundle uses single-pass compression to minimize binary size:
jlink runtime — Created with no internal compression, then compressed once via
tar.gzat maximum level. This avoids double-compression overhead (compressing already-compressed data). The--compressflag is probed fromjlink --help, since the accepted spelling (zip-0vs numeric0) varies across JDK builds.Application JAR — Compressed once with gzip at maximum level. When
--shrinkruns, it repacks the JAR with entries stored uncompressed so the gzip pass is the only compression step (Stored entries also load faster in the JVM).
Performance Tips
Use
--profile clifor command-line toolsKeep AppCDS enabled (default) for best startup
Consider CRaC for Linux deployments where startup is critical
Pre-warm in CI by running the binary once to generate AppCDS
Last updated
Was this helpful?