Jolta — the hands-off Java version manager

Jolta — the hands-off Java version manager

Like Volta, but for Java. Pin a JDK per project and never switch manually again.

macOSLinuxWindows zero dependenciesMIT

GitHub · Releases

$ cd my-service
$ jolta pin 21          # writes .java-version
$ java -version         # → OpenJDK 21, automatically

$ cd ../legacy-app      # has .java-version with "8"
$ java -version         # → 1.8 — no sdk use, no jenv shell, no export JAVA_HOME

Install

Prebuilt binaries for every platform — no Rust toolchain, no runtime, nothing to compile.

macOS Apple Silicon & Intel

Homebrew:

brew install OneAppPlatform/tap/jolta
jolta setup

Or the one-line installer:

curl -fsSL https://raw.githubusercontent.com/OneAppPlatform/jolta/main/install.sh | sh

Linux x86_64 & arm64 · static musl, any distro

One-line installer:

curl -fsSL https://raw.githubusercontent.com/OneAppPlatform/jolta/main/install.sh | sh

Or Homebrew on Linux:

brew install OneAppPlatform/tap/jolta
jolta setup

Windows x86_64

Download jolta-x86_64-pc-windows-msvc.zip from the releases page, unzip, then:

.\jolta.exe setup

Follow the two printed steps: add the shims directory to your user PATH, and add the PowerShell hook line to your $PROFILE.

Verify with a new shell:

jolta doctor

How it works

Jolta puts lightweight shims on your PATH (java, javac, jar, jshell, …) — each one a link to the single jolta binary. Every invocation walks up from the current directory to the nearest .java-version, resolves an installed JDK for it, sets JAVA_HOME, and execs the real tool. Resolution takes ~2 ms, invisible next to JVM startup.

If a project pins a version you don't have, the first invocation downloads it on demand (Volta-style) from the distro's official endpoint — never triggered by merely cd-ing around, safe under parallel builds, and disabled with JOLTA_NO_AUTO_INSTALL=1. Restricted networks can set JOLTA_DOWNLOAD_BASE to serve JDKs from an internal mirror ({base}/{vendor}/{version}/{os}-{arch}.{ext}) instead of the vendor endpoints.

Jolta also finds the JDKs you already have: Homebrew, /Library/Java/JavaVirtualMachines, SDKMAN, /usr/lib/jvm, Windows Program Files, and JAVA_HOME_<major>_* environment variables.

Pinning

The pin is a plain .java-version file (compatible with jenv and asdf) — commit it to your repo:

jolta pin 21        # this project uses Java 21
jolta default 21    # global fallback when a project has no pin

Resolution order: JOLTA_JAVA_VERSION env var → nearest .java-version walking up → jolta default → system default JDK. On a machine with no JDK at all, the first java run installs the latest LTS (Temurin) and sets it as your default.

A major pin (21) matches the highest installed build of that major. An exact pin (21.0.2) means exact — never silently substituted, and auto-installed precisely. .sdkmanrc files (java=21.0.2-tem) are honored with vendor mapping when no .java-version claims the directory. jolta catalog (alias search) shows what every distro publishes — latest per distro, per-major comparisons, and @v prefix filters like temurin@21.0 — with installed versions marked.

Distros

A spec can name a JDK distribution as distro@version or distro-version:

jolta pin corretto@21        # this project wants Amazon Corretto 21
jolta install graalvm@25     # explicitly fetch a GraalVM JDK

Point releases: jolta update checks jolta-managed JDKs against the vendors (via redirect filenames — no downloads) and jolta upgrade fetches newer builds and prunes superseded ones. Homebrew/system JDKs stay with their own package managers; resolution picks the highest build of a major, so their upgrades apply automatically.

JAVA_HOME, Maven & Gradle

Two mechanisms keep JAVA_HOME correct:

  1. Shims export it for everything they exec.
  2. The shell hook (installed by setup; zsh, bash, and PowerShell) re-resolves it every time you change directory — covering tools that read JAVA_HOME directly, like Maven, Gradle, and IDEs launched from a terminal. If a pin can't be satisfied the hook unsets JAVA_HOME, so builds fail loudly rather than silently using the wrong JDK.

Don't export JAVA_HOME manually in your profile — the hook owns it. In scripts and CI, use jolta exec mvn ... or eval "$(jolta env)". jolta doctor flags stale values.

Commands

CommandWhat it does
jolta setupInstall shims + shell profile setup
jolta pin <spec>Write .java-version in the current directory
jolta default <spec>Set the global fallback version
jolta install <spec>Download a JDK (21, corretto@21, graalvm@25)
jolta catalog [x]The JDK catalog: latest per distro/major, @v prefix filters (alias search)
jolta updateCheck jolta-managed JDKs for newer point releases
jolta upgrade [spec]Upgrade jolta-managed JDKs, pruning old builds
jolta uninstall <name>Remove a jolta-managed JDK
jolta listList visible JDKs with distro, star the active one
jolta jdksMachine-readable list: major / version / distro / home
jolta currentShow the version resolved here, and why
jolta which [tool]Full path the shim would exec
jolta exec <cmd>Run any command with JAVA_HOME/PATH set
jolta envPrint export lines for eval
jolta homePrint the resolved JAVA_HOME
jolta hook [shell]Print the cd hook (zsh, bash, powershell)
jolta reshimRegenerate shims after installing JDKs elsewhere
jolta doctorDiagnose PATH / shim / JAVA_HOME problems
jolta implodeUninstall jolta completely

How jolta compares

An honest table, current as of July 2026 — corrections welcome.

joltamiseSDKMANjenvasdf
.java-version honored by default opt-inopt-in
.sdkmanrc honored opt-inopt-in
JAVA_HOME set automatically opt-inpluginplugin
Downloads JDKs
Auto-install on first java run partial
Exact point-release pinning partial
GraalVM manual
Finds JDKs you already have (brew, system) manual
Point-release upgrades with cleanup manual
Remote catalog browsing
Native Windows WSL
Corporate mirror support partialpartial
Also manages Maven/Gradle/other tools
Zero config files of its own
Battle-tested since 20262023201220112014

Fair summary: if Java is one of five languages you juggle, mise is excellent. If Java is the job, jolta does the whole job by default — nothing to enable, nothing to configure, and a .java-version is all your repo needs.

Uninstall

jolta implode

Removes ~/.jolta and the jolta lines from your shell profile, after a confirmation prompt that lists exactly which jolta-installed JDKs will be deleted. JDKs installed outside jolta and your .java-version files are never touched — jolta only ever deletes what it downloaded itself.