codeworking.org
Search
Developer Skill / Gist

Mastering SDKMAN!

Modern JVM Tooling: SDKMAN! (Software Development Kit Manager) is a lightweight, open-source CLI tool for managing parallel versions of multiple Software Development Kits across Unix-like systems (macOS, Linux, and Windows via WSL/Git Bash). By managing JAVA_HOME, PATH, and build tool binaries entirely in user-space, SDKMAN! eliminates environment pollution and version friction.


1. Why SDKMAN!? The Multi-Runtime Challenge

Modern backend engineering frequently requires juggling incompatible SDK versions across legacy and greenfield projects:

  • Project A requires Java 8 and Maven 3.6.
  • Project B requires Java 17 (LTS) and Gradle 7.6.
  • Project C requires Java 21 (LTS) or preview builds of Java 25, Kotlin 2.0, and Micronaut.

Manually downloading tarballs, untarring them into /Library/Java/ or /opt/, and manually updating .zshrc / .bashrc environment variables is brittle and error-prone.

SDKMAN! solves this by providing a unified, declarative package manager for JVM and cloud-native toolchains that operates completely in user-space (~/.sdkman) without requiring sudo privileges.


SDKMAN! uses a deterministic directory layout and dynamic filesystem symlinks to switch active toolchains instantly.

~/.sdkman/
├── bin/                 # SDKMAN! shell entry scripts & Rust native binary
├── candidates/          # Installed SDK binaries
│   ├── java/
│   │   ├── 17.0.12-tem/ # Eclipse Temurin JDK 17
│   │   ├── 21.0.4-tem/  # Eclipse Temurin JDK 21
│   │   └── current ────> symlink to active version (e.g. 21.0.4-tem)
│   ├── gradle/
│   │   ├── 8.5/
│   │   └── current ────> symlink to active version
│   └── maven/
│       ├── 3.9.9/
│       └── current ────> symlink to active version
└── etc/
    └── config           # Global configuration settings
+-------------------------------------------------------------------------+
|                        Terminal Shell (zsh / bash)                      |
+-------------------------------------------------------------------------+

                  Intercepts command or `sdk use`

                                    v
+-------------------------------------------------------------------------+
|                        SDKMAN! Environment Engine                       |
|   1. Updates `JAVA_HOME` ──> ~/.sdkman/candidates/java/current          |
|   2. Prepend active binary paths to `$PATH` in memory                   |
|   3. Updates dynamic symlink pointers                                  |
+-------------------------------------------------------------------------+

Key Architectural Advantages

  1. Zero Sudo / User Space: All binaries reside in $HOME/.sdkman/candidates/, preventing permission conflicts and keeping the root OS filesystem clean.
  2. Instant In-Memory Switching (sdk use): Switches the runtime for the current shell session only, allowing two terminal tabs to run completely different JDK versions simultaneously.
  3. Global Persistence (sdk default): Updates the current symlink to establish system-wide defaults for new shell windows.
  4. Rust-Powered High-Performance Core: Integrates native Rust components for ultra-fast candidate resolution, metadata parsing, and network downloads.

3. Installation & Verification

Standard Installation

Open your terminal on macOS, Linux, or WSL and run:

# 1. Download and run the official installer script
curl -s "https://get.sdkman.io" | bash

# 2. Source the initialization snippet into your current shell
source "$HOME/.sdkman/bin/sdkman-init.sh"

# 3. Verify successful installation
sdk version

Prerequisites

SDKMAN! requires standard POSIX utilities: curl, zip, unzip, tar, and sed. On minimal Linux/Docker images:

# Debian / Ubuntu
sudo apt-get update && sudo apt-get install -y curl zip unzip

# RHEL / Fedora / AlmaLinux
sudo dnf install -y curl zip unzip

4. Daily CLI Mastery: Essential Candidate Workflows

In SDKMAN! terminology, an SDK (like Java, Kotlin, Maven, Gradle, or Scala) is called a Candidate.

4.1 Discovering Available Candidates & Versions

# List all supported toolchains (Java, Gradle, Maven, Kotlin, Scala, Quarkus, etc.)
sdk list

# List all available distributions and versions for Java
sdk list java

# List available versions for build tools
sdk list gradle
sdk list maven

4.2 Installing SDKs

SDKMAN! supports all major OpenJDK distributions (Temurin, Corretto, GraalVM, Liberica, Microsoft, Oracle, Zulu, Semeru):

# Install Eclipse Temurin JDK 21 (LTS)
sdk install java 21.0.4-tem

# Install Amazon Corretto JDK 17
sdk install java 17.0.12-amzn

# Install GraalVM for native compilation
sdk install java 21.0.2-graal

# Install latest stable Gradle and Maven
sdk install gradle
sdk install maven 3.9.9

4.3 Switching Versions: Session vs Global Default

# Set a GLOBAL default version (persists across all new terminal windows)
sdk default java 21.0.4-tem

# Switch version TEMPORARILY in the current shell session only
sdk use java 17.0.12-amzn

# Check currently active versions
sdk current
sdk current java

4.4 Maintenance & Cleanup

# Uninstall a specific version
sdk uninstall java 11.0.2-open

# Clear downloaded zip archives and temporary files to free disk space
sdk flush archives
sdk flush temp

# Check health and sync with upstream metadata broker
sdk update

5. Project-Level Environments (.sdkmanrc & Auto-Env)

Instead of relying on team members to manually remember which JDK or Gradle version a project needs, SDKMAN! provides declarative project configuration through .sdkmanrc files.

5.1 Creating a Project Configuration

Navigate to your project repository root:

# Generate a .sdkmanrc file with your current active toolchain
sdk env init

This generates a .sdkmanrc file:

# .sdkmanrc
java=21.0.4-tem
gradle=8.10
maven=3.9.9

5.2 Activating the Environment

When a developer clones your repo:

# Install any missing SDKs declared in .sdkmanrc
sdk env install

# Activate the declared versions for the current shell
sdk env

5.3 Enabling Automatic Directory Switching (auto-env)

You can configure SDKMAN! to automatically switch versions whenever you cd into a directory containing a .sdkmanrc:

  1. Open ~/.sdkman/etc/config:
    nano "$HOME/.sdkman/etc/config"
  2. Enable automatic environment hooks:
    sdkman_auto_env=true
    sdkman_auto_answer=false
  3. Whenever you navigate into a project folder, SDKMAN! silently sets JAVA_HOME and $PATH to match the project’s exact requirements!

6. Registering Local & Custom SDK Builds

If you build custom OpenJDK distributions locally, or download proprietary vendor SDKs, you can register them directly with SDKMAN!:

# Syntax: sdk install <candidate> <custom-identifier> <local-path>
sdk install java custom-graalvm /opt/graalvm-ce-java21-21.0.2

# Now use your local build like any standard SDKMAN! candidate
sdk use java custom-graalvm

7. Offline Mode & Air-Gapped Environments

When traveling or working inside secure corporate networks with restricted internet access:

# Enable offline mode (prevents network queries to the SDKMAN! broker)
sdk offline enable

# Work with all locally installed candidates seamlessly
sdk use java 21.0.4-tem

# Re-enable online mode when connected
sdk offline disable

8. Ecosystem Comparison: Version Managers

Feature SDKMAN! jEnv asdf-vm Homebrew WinGet
Primary Domain JVM Ecosystem & Cloud Tools Java JDKs Only Polyglot (Node, Python, Ruby, etc.) macOS / Linux General Packages Windows General Applications
Sudo Required ❌ No (User space) ❌ No ❌ No ❌ No ⚠️ Windows UAC
Auto-Env (.rc) ✅ Built-in (.sdkmanrc) ✅ (.java-version) ✅ (.tool-versions) ❌ No ❌ No
Multi-Vendor JDKs ✅ 15+ OpenJDK Distributions ⚠️ Local registration only ⚠️ Plugin dependent ⚠️ Limited versions ⚠️ Vendor MSI packages
Build Tools ✅ Maven, Gradle, SBT, Ant ❌ No ✅ Via plugins ✅ Global only ⚠️ Global only
Local Custom Builds ✅ First-class (sdk install) ✅ First-class ⚠️ Complex ❌ No ❌ No

9. Global Configuration Reference (~/.sdkman/etc/config)

# ~/.sdkman/etc/config

# Automatically switch environment when entering a directory with .sdkmanrc
sdkman_auto_env=true

# Automatically accept prompts during non-interactive scripts
sdkman_auto_answer=false

# Automatically check for SDKMAN! CLI updates
sdkman_selfupdate_feature=true

# Enable native curl / Rust accelerated downloads
sdkman_curl_connect_timeout=7
sdkman_curl_max_time=10

10. Summary & Cheat Sheet

# 🔍 Exploration
sdk list java                  # Browse all OpenJDK vendors & versions
sdk list                       # Browse all supported developer candidates

# 📦 Installation & Defaults
sdk install java 21.0.4-tem    # Install specific candidate version
sdk default java 21.0.4-tem    # Set global default JDK
sdk use java 17.0.12-amzn      # Temporary shell-scoped switch

# 📁 Project Environment (.sdkmanrc)
sdk env init                   # Create .sdkmanrc in current folder
sdk env install                # Install missing tools for project
sdk env                        # Manually load project environment

# 🧹 Maintenance
sdk current                    # Show active candidates and versions
sdk flush archives             # Free up disk space
sdk update                     # Sync upstream candidate catalogs

SDKMAN! is the gold standard for JVM environment orchestration, enabling friction-free development across legacy systems, enterprise LTS releases, and bleeding-edge cloud-native architectures.

S

Computer Science educator, Software Engineer, Cloud Computing & Cloud Native Architect, and AI/ML Engineer. Founder & Owner of unus.one, softwork.ing, and codeworking.org.

Comments & Discussion