🏠 Overview • 📦 Installation • 📖 Usage • 🏗️ Architecture • ❓ FAQ • ⚖️ SDKMAN! Comparison • 📜 Changelog • 🛡️ Security • 🤝 Contributing • 💬 Support
SDKMAN! is the industry standard for managing Java versions and ecosystem tools. However, for native Windows users, it presents strict architectural challenges.
SDKMAN! is a collection of POSIX-compliant Bash scripts. To run it on Windows, developers must install heavy compatibility layers like Windows Subsystem for Linux (WSL), MSYS2, or Git Bash. While this works well for Linux-first workflows, it causes severe friction for native Windows developers:
- IDE Disconnect: JDKs installed inside WSL are not easily accessible by native Windows IDEs (like IntelliJ or VS Code) without setting up complex remote-bridge configurations.
- I/O Performance: Crossing the OS boundary between WSL and the native Windows filesystem (
/mnt/c/) causes notoriously slow read/write speeds, increasing build times for Maven and Gradle. - Environment Variables: SDKMAN! updates
.bashrc, which Windowscmd.exeand background services completely ignore.
This Java Version Manager (jvm.bat) solves this by operating directly on the Windows Registry, native NTFS Directory Junctions, and pure CMD/PowerShell environments.
| Feature | SDKMAN! (on Windows) | Java Version Manager (Native) |
|---|---|---|
| Runtime | Bash / curl / zip |
Native Batch / PowerShell / .NET |
| Dependencies | WSL, Cygwin, or Git Bash | None (Works out-of-the-box) |
| Supported Shells | Bash / Zsh only (inside compatibility layer) | CMD, Windows PowerShell, PS Core, Windows Terminal |
| I/O Speed | Slower (Virtualization boundary) | Maximum (Native NTFS) |
| Integration | .bash_profile / .zshrc |
Windows Registry (JAVA_HOME, PATH) |
| Switching Engine | POSIX Symlinks (requires Developer Mode) | Dual Engine: UAC-Free NTFS Junctions & Registry Mode |
| Switching Syntax | Verbose candidate slugs (sdk use java 21.0.2-tem) |
1-Word Shorthand (jvm 21, jvm lts, jvm latest) |
| Live Broadcasting | Shell-only (requires source or restart) |
Win32 WM_SETTINGCHANGE + Live In-Memory Hot Patch |
| IDE Support | Requires WSL bridges | 100% Native (IntelliJ, Eclipse, VS Code) |
| Windows Services & GUI | Inaccessible to Windows services | Full System Visibility (Jenkins, SonarQube, Task Scheduler, Start Menu) |
| Project File Support | .sdkmanrc only |
Dual Support: .java-version & Auto .sdkmanrc Translation |
| Local JDK Discovery | Cannot scan Windows folders | Automatic Local Discovery (scans Program Files for existing JDKs) |
| Offline Operation | May lag on remote API latency | Zero-Ping Local Switching (100% offline, instant) |
| Pre-Change Safety | None (overwrites shell files) | Automated Registry Backups (exports .reg to %LOCALAPPDATA%\DiamTek\JVM\backups\) |
| User Interface | CLI Only (Manual typing) | Interactive TUI & Headless CLI |
| Archive Extraction | Requires external zip / tar binaries |
Native .NET System.IO.Compression |
| Security Validation | Basic (curl downloads) |
Strict .NET SHA256/SHA512 Cryptography |
| CPU Architecture | Manual configuration | Native x64 / ARM64 Auto-Detection |
| Bulk Maintenance | Manual, tool-by-tool | 1-Click Bulk Updater (jvm update --all) |
| Self-Updater & Channels | Single-channel script pull (sdk selfupdate) |
Dual Channels (🟢 Stable / 🟣 Nightly) with SHA-256 integrity, ahead-of-remote block & rate-limit fallback |
| OS Conflict Handling | Passive | Active Phantom-Path Scrubbing |
| Status & Binary Inspection | sdk current (POSIX shell string) |
jvm current & jvm which (Full status card + binary resolver) |
| Cache & Slate Cleaning | sdk flush (basic temp deletion) |
jvm clean & jvm clear (Deep cache purge & registry slate wipe) |
| Ephemeral Subshell Runner | None (must switch shell and restore) | jvm exec <ver> [--] <cmd> / jvm run (zero global changes, accurate exit codes) |
| Diagnostic Health Audit | None | jvm doctor (7-point deep conflict, junction, & shadowing analysis) |
| Project Pinning CLI | Manual .sdkmanrc editing |
jvm pin [ver] / jvm local (instant lock writing & display) |
| Migration Muscle Memory | sdk use / sdk default |
jvm use / jvm default (1:1 transparent compatible aliases) |
| File Explorer Jump | Manual path navigation | jvm open [candidate] / jvm home (Instant GUI explorer jump) |
| Shell Wrapper Hook | Manual source line in .bashrc/.zshrc |
jvm hook (Automated install, status, and removal for PS 5.1 & PS 7+) |
| Enterprise Proxies | Manual http_proxy env exports |
Native Windows WinINet & Corporate Certificate Store |
| Windows Packaging | Unofficial / None | Winget, Scoop, Chocolatey, & Native MSI |
| Enterprise Privileges | Requires WSL/Bash setup | Zero-Admin / 0 UAC (Runs on locked-down corporate laptops) |
| Corporate Fleet Rollout | None (Manual shell curl) | Silent Intune, MECM & GPO MSI (msiexec /qn) |
| Uninstallation | Manual script deletion | Deep UAC Uninstaller & Windows Settings Integration |
You don't need SDKMAN! just to get Maven or Gradle on Windows. This tool features a built-in Universal Candidate Engine that provides 1:1 ecosystem parity with SDKMAN!. It natively downloads, extracts, and routes modern JVM build tools directly from Apache and GitHub APIs.
- Supported natively: Maven, Gradle, Kotlin, Scala, Groovy.
The biggest hurdle for Windows developers is collaborating on repositories maintained by Mac/Linux developers who commit a .sdkmanrc file to the root of the project.
This tool completely eliminates that friction. It features a native .sdkmanrc parser that dynamically "hijacks" SDKMAN! workflows:
- When you run
jvmin a folder with a.sdkmanrcfile, it reads the exact versions requested by the Linux team. - It translates SDKMAN! vendor strings (e.g.,
17-tem,21-amzn,21-librca, or21-sem) into their native Windows equivalents (Adoptium, Corretto, Liberica, Semeru). - It instantly isolates the exact requested JDK, Maven, and Gradle versions into your current terminal session.
You get 100% perfect environment synchronization with your Linux teammates, without ever installing a Linux subsystem on your Windows machine.
In SDKMAN!, switching versions requires knowing and typing the exact candidate slug:
# SDKMAN! (POSIX syntax)
sdk use java 21.0.2-tem
sdk default java 17.0.10-amznIf you forget the vendor suffix or patch release, you are forced to run sdk list java, search through hundreds of lines, and copy-paste the exact string.
DiamTek JVM provides 1-Word Shorthand Ergonomics alongside transparent SDKMAN! aliases:
# DiamTek JVM (Native Windows shorthand)
jvm 21
jvm lts
jvm latest
# SDKMAN! / NVM Migration Aliases (supported 1:1)
jvm use 21
jvm default 21
# Session-isolated switch (matching SDKMAN 'sdk use' semantics)
jvm use 21 --sessionNote on
jvm usevsjvm default: In SDKMAN!,sdk useapplies strictly to the current shell whilesdk defaultchanges the global symlink. In DiamTek JVM, standard switches (jvm 21,jvm use 21,jvm default 21) switch the active JDK globally via the Directory Junction to match the Windowsnvm-windowsconvention. To get SDKMAN's session-isolated behavior, simply pass--session(jvm use 21 --session).
JVM automatically inspects your installed versions and routes to the best installed candidate. If you have multiple distributions installed for the same major version (e.g., both Oracle JDK 21 and Eclipse Temurin 21), JVM pauses and displays an interactive prompt asking you to pick your preferred vendor—or you can override it directly via --vendor (e.g., jvm 21 --vendor adoptium).
In SDKMAN!, running a one-off build or test against a different JDK requires switching your current shell (sdk use java 17...), executing the build, and then manually switching back (sdk use java 21...). If the build crashes or you forget to revert, your shell remains stuck on the wrong Java version.
DiamTek JVM provides native, one-line ephemeral execution:
# Runs in an ephemeral child subshell with zero global changes
jvm exec 17 -- mvn clean test
# Alias: jvm run 17 mvn clean test- Zero Global Side Effects: Leaves your active Directory Junction (
current), global Windows Registry, and other terminal windows completely untouched. - Strict Exit Code Fidelity: Captures and propagates the child process's exact exit code (
0or non-zero) back to the calling shell, ensuring CI/CD and automation runners fail accurately when builds break.
Windows developers frequently face silent environment breaks caused by rogue MSI installers, broken directory junctions, or mismatched User/Machine registries. SDKMAN! has no diagnostic command to analyze underlying OS health or identify why a tool is malfunctioning.
DiamTek JVM includes jvm doctor—an automated 7-point health auditor:
jvm doctor- Audits AppData local storage permissions.
- Verifies Directory Junction integrity and
bin\java.exetarget reachability. - Synchronizes User (
HKCU) and Machine (HKLM) registry states. - Scans
where.exe javafor legacy OraclejavapathandSystem32shadowing. - Verifies PowerShell
$PROFILEhook status. - Returns standard exit code
0on clean health or1on warnings, making it an ideal pre-flight check for enterprise deployment scripts.
In SDKMAN!, locking a project to a specific runtime requires manually writing or updating a .sdkmanrc file by hand.
DiamTek JVM provides dedicated CLI commands for project pinning:
# Lock project to JDK 21 (.java-version)
jvm pin 21
# Lock with vendor flags
jvm pin 21 --vendor adoptium
# Inspect active project pin
jvm pin
# Alias: jvm localWhenever a developer runs jvm inside that directory, JVM automatically reads the .java-version file and locks the terminal session to that version without touching the global registry.
Finding where a JDK or build tool is physically stored on disk in Windows usually requires traversing hidden AppData directories or system folders.
With DiamTek JVM, you can jump directly to any installed runtime or candidate folder in Windows File Explorer:
# Open active JDK directory in File Explorer
jvm open
# Open specific tool candidate folder
jvm open maven
jvm open gradle
# Open the JVM storage root
jvm open root
# Alias: jvm homeIn SDKMAN!, integrating with developer shells requires manually maintaining a source "$HOME/.sdkman/bin/sdkman-init.sh" block inside .bashrc or .zshrc. If that initialization script becomes corrupted, debugging it requires manual text editing.
DiamTek JVM provides dedicated, one-command shell hook lifecycle management:
# Install or update the auto-sync wrapper hook in PowerShell profiles
jvm hook install
# Check hook status across Windows PowerShell 5.1 and PowerShell 7+
jvm hook status
# Cleanly remove the wrapper hook without touching other profile settings
jvm hook remove- Automated Multi-Shell Discovery: Automatically detects and manages both Windows PowerShell (5.1) and modern PowerShell Core (7+) profiles across standard and OneDrive-redirected Documents folders.
- In-Memory Session Sync: Whenever you switch JDKs (
jvm 21), the hook dynamically updates$env:JAVA_HOMEand$env:Pathin-memory across the active shell session without restarting your terminal window.
When configuring Windows IDEs (IntelliJ IDEA, Eclipse, VS Code), native scripts, or CI/CD pipelines, you need to know where the actual Windows executable is located. Under WSL or Git Bash, which java returns a virtualized Linux path (/home/user/.sdkman/candidates/java/current/bin/java) that Windows applications cannot resolve without conversion bridges like wslpath -w.
DiamTek JVM provides native Windows inspection tools:
jvm current(orjvm status): Displays a comprehensive overview card detailing the active JDK version, vendor,JAVA_HOME, resolved executable, switching mode ([Symlink Mode]vs[Registry Mode]), junction link, and active ecosystem tools (Maven, Gradle, Kotlin).jvm which [candidate](orjvm path): Prints the absolute Windows filesystem path to the active binary directly tostdout. Works seamlessly for Java (jvm which) and ecosystem build tools (jvm which maven,jvm which gradle). Ideal for automation scripts and IDE path configurations:# PowerShell automation $javaExe = (jvm which) & $javaExe -version
Managing development environments requires both disk space hygiene and environment sanitization. In SDKMAN!, cache cleanup is limited to sdk flush, while de-activating an environment requires manually editing .bashrc and deleting symlinks.
DiamTek JVM cleanly decouples these two maintenance workflows:
jvm clean(Disk Cache Pruner): Safely sweeps%TEMP%and%LOCALAPPDATA%\DiamTek\JVMto purge orphaned.zipand.tar.gzdownloads, temporary extraction trees, and obsolete updater scripts. It calculates and reports the exact number of files deleted and megabytes reclaimed without touching active JDKs or settings.jvm clear(Environment Slate Wipe): Performs a deep system reset. It removesJAVA_HOME, scrubs rogue Oraclejavapathentries and broken junctions from both User and MachinePATH, and restores a clean baseline. To ensure complete safety,jvm clearautomatically exports a timestamped.regregistry backup to%LOCALAPPDATA%\DiamTek\JVM\backups\before executing.
- Pre-Change Safety: Unlike POSIX shell scripts that directly overwrite
.bashrcor.zshrc, DiamTek JVM automatically creates a timestamped.regbackup in%LOCALAPPDATA%\DiamTek\JVM\backups\before making destructive registry modifications or clearing paths. If you ever need to roll back, simply double-click the.regfile to restore your previous environment state. - Zero-Ping Local Switching: SDKMAN! can occasionally lag or stall on poor network connections when running version queries against remote servers. DiamTek JVM executes local version switches 100% offline with zero network latency, making it completely reliable in air-gapped corporate environments, remote locations, and on planes.