jvr

Crates.iojvr
lib.rsjvr
version0.3.2
created_at2024-06-29 08:27:53.051862+00
updated_at2026-01-05 16:40:40.559887+00
descriptionA simple and easy-to-use Java version manager (registry: jvr), similar to Node.js's nvm, but it does not follow nvm's naming convention. Otherwise, it would be named 'jvm', which could cause command conflicts or ambiguity.
homepagehttps://github.com/photowey/jvr
repositoryhttps://github.com/photowey/jvr
max_upload_size
id1287217
size103,166
changjun (photowey)

documentation

https://docs.rs/jvr

README

jvr

A simple and easy-to-use Java version manager (registry: jvr), similar to Node.js's nvm, but it does not follow nvm's naming convention. Otherwise, it would be named jvm, which could cause command conflicts or ambiguity.


✨ What's New in v0.3.2

More robust and permission-friendly directory linking on Windows:

  • 🪩 Junctions instead of symlinks on Windows: Directory links now use NTFS junctions instead of symbolic links, eliminating the need for administrator privileges or Developer Mode
  • 🔗 Seamless folder redirection: Linking a JDK directory (e.g., jdk11) to a init($ jvr init /path/to/java_home) location (e.g., /path/to/xxx) works reliably for all standard users on Windows
  • 🧼 Safe cleanup: Existing links—whether junctions, symlinks, or regular directories—are correctly and safely removed before recreation
  • 💻 Cross-platform consistency: Unix-like systems continue using symbolic links as before; only Windows behavior is optimized for usability and security

0.Platform Support

jvr supports the following operating systems:

  • Windows (Windows 10/11)
  • Linux (various distributions)
  • macOS (various versions)

1.Install

1.1.Download executable

Download the executable file directly from GitHub and put it in any $PATH path.

1.2.Cargo

# 1.github
$ cargo install --git https://github.com/photowey/jvr.git [--branch main]

# 2.crates.io
$ cargo install jvr

1.3.Build from source

git clone https://github.com/photowey/jvr.git
cd jvr
cargo build --release

2.Usage

2.1.Quick Start

First-time setup (required):

# Step 1: Initialize jvr with a JAVA_HOME path
$ jvr init /path/to/java_home

# Step 2: Add JDK versions
$ jvr add jdk8 /path/to/jdk8
$ jvr add jdk11 /path/to/jdk11

# Step 3: Switch between JDK versions
$ jvr use jdk11

Complete Workflow Diagram:

sequenceDiagram
    participant User
    participant jvr
    participant Filesystem
    participant EnvVars
    
    Note over User,EnvVars: Step 1: Initialize (One-time)
    User->>jvr: jvr init ~/.jvr/java_home
    jvr->>Filesystem: Create JAVA_HOME directory
    jvr->>EnvVars: Set JAVA_HOME environment variable
    jvr->>EnvVars: Add JAVA_HOME/bin to PATH
    jvr->>Filesystem: Save JAVA_HOME path to config.json
    jvr->>User: Initialized
    
    Note over User,EnvVars: Step 2: Add JDK Versions
    User->>jvr: jvr add jdk8 /path/to/jdk8
    jvr->>Filesystem: Verify JDK path exists
    jvr->>Filesystem: Save JDK info to config.json
    jvr->>User: Added
    
    User->>jvr: jvr add jdk11 /path/to/jdk11
    jvr->>Filesystem: Verify JDK path exists
    jvr->>Filesystem: Save JDK info to config.json
    jvr->>User: Added
    
    Note over User,EnvVars: Step 3: Switch JDK (Fast)
    User->>jvr: jvr use jdk11
    jvr->>Filesystem: Remove old symlink (if exists)
    jvr->>Filesystem: Create symlink JAVA_HOME to /path/to/jdk11
    jvr->>Filesystem: Update current JDK in config.json
    jvr->>User: Switched
    
    Note over User,EnvVars: Subsequent switches are instant
    User->>jvr: jvr use jdk8
    jvr->>Filesystem: Update symlink JAVA_HOME to /path/to/jdk8
    jvr->>User: Switched (No env var update needed)

2.2.Commands

2.2.1Init (v0.3.0+)

Initialize jvr with a JAVA_HOME path. This command must be run once before using other commands.

What it does:

  • Creates the JAVA_HOME directory if it doesn't exist
  • Sets the JAVA_HOME environment variable
  • Adds JAVA_HOME/bin to your PATH environment variable
$ jvr init -h | --help
$ jvr init <JAVA_HOME_PATH>

# e.g.:
$ jvr init ~/.jvr/java_home
$ jvr init "C:\Users\YourName\.jvr\java_home"

Note: After running jvr init, you may need to reload your shell configuration (Unix) or restart your terminal (Windows) for the environment variables to take effect.

Command Flow:

flowchart TD
    START(["jvr init path"]) --> CHECK{"Path exists?"}
    CHECK -->|No| CREATE["Create directory"]
    CHECK -->|Yes| SET_ENV["Set JAVA_HOME env var"]
    CREATE --> SET_ENV
    SET_ENV --> CHECK_PATH{"JAVA_HOME/bin in PATH?"}
    CHECK_PATH -->|No| ADD_PATH["Add JAVA_HOME/bin to PATH"]
    CHECK_PATH -->|Yes| SAVE_CONFIG["Save JAVA_HOME path to config.json"]
    ADD_PATH --> SAVE_CONFIG
    SAVE_CONFIG --> SUCCESS(["Initialized"])
    
    style START fill:#e3f2fd
    style SUCCESS fill:#c8e6c9
    style CREATE fill:#fff9c4
    style SET_ENV fill:#fff9c4
    style ADD_PATH fill:#fff9c4

2.2.2Add

Register a JDK version with an alias name.

$ jvr add -h | --help
$ jvr add <NAME> <PATH>

# e.g.:
$ jvr add jdk8 /usr/lib/jvm/java-8-openjdk
$ jvr add jdk11 /usr/lib/jvm/java-11-openjdk
$ jvr add jdk17 "C:\Program Files\Java\jdk-17"

Note: This command only registers the JDK path. It does not modify environment variables.

Command Flow:

flowchart TD
    START(["jvr add name path"]) --> CHECK_EXISTS{"JDK already registered?"}
    CHECK_EXISTS -->|Yes| EXISTS_MSG["Print: Already added"]
    CHECK_EXISTS -->|No| CHECK_PATH{"Path exists?"}
    CHECK_PATH -->|No| ERROR["Error: Path not found"]
    CHECK_PATH -->|Yes| ADD["Add to versions list"]
    ADD --> SAVE["Save to config.json"]
    SAVE --> LIST["Display JDK list"]
    EXISTS_MSG --> LIST
    LIST --> END(["Complete"])
    ERROR --> END
    
    style START fill:#e3f2fd
    style END fill:#c8e6c9
    style ERROR fill:#ffcdd2
    style ADD fill:#fff9c4
    style SAVE fill:#fff9c4

2.2.3List

List all registered JDK versions in a formatted table. The * indicates the version currently in use.

$ jvr list

2.2.4Use

Switch to a specific JDK version by creating a symlink from JAVA_HOME to the selected JDK path.

$ jvr use <NAME>

# e.g.:
$ jvr use jdk11

How it works (v0.3.0+):

  • Creates a symlink from the JAVA_HOME path (set by init) to the selected JDK path
  • No need to update environment variables after the first init
  • Fast switching without modifying system configuration

Note: You must run jvr init before using this command.

Command Flow:

flowchart TD
    START(["jvr use name"]) --> CHECK_INIT{"Initialized?"}
    CHECK_INIT -->|No| INIT_ERROR["Error: Run jvr init first"]
    CHECK_INIT -->|Yes| FIND_JDK{"Find JDK by name"}
    FIND_JDK -->|Not found| NOT_FOUND["Error: JDK not found"]
    FIND_JDK -->|Found| CHECK_PATH{"JDK path exists?"}
    CHECK_PATH -->|No| PATH_ERROR["Error: Path not found"]
    CHECK_PATH -->|Yes| REMOVE_OLD{"Old symlink exists?"}
    REMOVE_OLD -->|Yes| DELETE["Remove old symlink"]
    REMOVE_OLD -->|No| CREATE_SYMLINK["Create symlink JAVA_HOME to JDK"]
    DELETE --> CREATE_SYMLINK
    CREATE_SYMLINK --> UPDATE_CURRENT["Update current JDK in config"]
    UPDATE_CURRENT --> SAVE["Save config.json"]
    SAVE --> LIST["Display JDK list"]
    LIST --> SUCCESS(["Switched"])
    INIT_ERROR --> END(["Exit"])
    NOT_FOUND --> END
    PATH_ERROR --> END
    
    style START fill:#e3f2fd
    style SUCCESS fill:#c8e6c9
    style INIT_ERROR fill:#ffcdd2
    style NOT_FOUND fill:#ffcdd2
    style PATH_ERROR fill:#ffcdd2
    style CREATE_SYMLINK fill:#fff9c4
    style UPDATE_CURRENT fill:#fff9c4

2.2.5Version

View the version of jvr itself.

$ jvr version

2.2.6Open

Open the directory where jvr configuration is located.

$ jvr open

3.How It Works (v0.3.0)

3.1.Symlink-Based Architecture

jvr v0.3.0 uses a symlink-based approach for faster JDK switching:

  1. Initialization (jvr init): Sets up a fixed JAVA_HOME path and configures environment variables once
  2. Adding JDKs (jvr add): Registers JDK paths without modifying environment variables
  3. Switching JDKs (jvr use): Creates/updates a symlink from JAVA_HOME to the selected JDK

Benefits:

  • Fast switching: No need to update environment variables on each switch
  • 🔒 Stable JAVA_HOME: JAVA_HOME path remains constant, only the symlink target changes
  • 🎯 One-time setup: Environment variables configured once during init

3.1.1.Architecture Diagram

graph TB
    subgraph UserEnv["User Environment"]
        JAVA_HOME["JAVA_HOME<br/>(Fixed Path)"]
        PATH["PATH<br/>(Includes JAVA_HOME/bin)"]
    end
    
    subgraph JvrMgmt["jvr Management"]
        SYMLINK["Symlink<br/>(JAVA_HOME to JDK)"]
        CONFIG["config.json<br/>(JDK Registry)"]
    end
    
    subgraph JDKInst["JDK Installations"]
        JDK8["JDK 8<br/>/path/to/jdk8"]
        JDK11["JDK 11<br/>/path/to/jdk11"]
        JDK17["JDK 17<br/>/path/to/jdk17"]
    end
    
    JAVA_HOME -->|Points to| SYMLINK
    SYMLINK -->|Links to| JDK11
    CONFIG -->|Stores| JDK8
    CONFIG -->|Stores| JDK11
    CONFIG -->|Stores| JDK17
    
    style JAVA_HOME fill:#e1f5ff
    style SYMLINK fill:#fff4e1
    style CONFIG fill:#e8f5e9
    style JDK11 fill:#ffebee

3.2.Configuration File Location

jvr stores its configuration in:

  • Windows: %USERPROFILE%\.jvr\config.json
  • Linux/macOS: ~/.jvr/config.json

The configuration file stores:

  • The JAVA_HOME path (set by init)
  • List of registered JDK versions
  • Currently active JDK alias

3.3.Environment Variables

jvr manages the following environment variables:

  • JAVA_HOME: Set to the path specified in jvr init (configured once)
  • PATH: Automatically includes $JAVA_HOME/bin (Unix) or %JAVA_HOME%\bin (Windows)

Important: After running jvr init, you need to:

  • Unix: Reload your shell configuration (source ~/.bashrc or source ~/.zshrc)
  • Windows: Restart your terminal or log out and log back in

3.4.Shell Configuration Files (Unix)

On Unix systems (Linux/macOS), jvr automatically detects your shell and writes environment variables to the appropriate configuration file:

  • Zsh: ~/.zshrc, ~/.zshenv
  • Bash: ~/.bashrc, ~/.bash_profile, ~/.profile
  • Default: ~/.profile

The tool will use the first available file in the list above.

4.Examples

4.1.Complete Workflow

# Step 1: Initialize jvr (one-time setup)
$ jvr init ~/.jvr/java_home
✅ Created JAVA_HOME directory: /home/user/.jvr/java_home
✅ jvr initialized successfully!
   JAVA_HOME: /home/user/.jvr/java_home
   Use 'jvr use <alias>' to switch between JDK versions.

# Reload shell configuration (Unix only)
$ source ~/.bashrc  # or ~/.zshrc

# Step 2: Add JDK versions
$ jvr add jdk8 /usr/lib/jvm/java-8-openjdk
✅ Added JDK version: ['jdk8']

$ jvr add jdk11 /usr/lib/jvm/java-11-openjdk
✅ Added JDK version: ['jdk11']

$ jvr add jdk17 /usr/lib/jvm/java-17-openjdk
✅ Added JDK version: ['jdk17']

# Step 3: List all registered JDKs
$ jvr list
+-----+-------+----------------------------------+---------+
| #   | Alias | Path                             | Current |
+=====+=======+==================================+=========+
| 1   | jdk8  | /usr/lib/jvm/java-8-openjdk      | -       |
| 2   | jdk11 | /usr/lib/jvm/java-11-openjdk     | -       |
| 3   | jdk17 | /usr/lib/jvm/java-17-openjdk     | -       |
+-----+-------+----------------------------------+---------+

# Step 4: Switch to a specific JDK version
$ jvr use jdk17
✅ Now using JDK jdk17 at /usr/lib/jvm/java-17-openjdk
   JAVA_HOME symlink: /home/user/.jvr/java_home -> /usr/lib/jvm/java-17-openjdk

# Verify the change
$ echo $JAVA_HOME
/home/user/.jvr/java_home

$ java -version
openjdk version "17.0.x" ...

# Switch to another JDK (fast, no environment variable update needed)
$ jvr use jdk11
✅ Now using JDK jdk11 at /usr/lib/jvm/java-11-openjdk
   JAVA_HOME symlink: /home/user/.jvr/java_home -> /usr/lib/jvm/java-11-openjdk

4.2.Platform-Specific Examples

Windows:

# Initialize
$ jvr init "C:\Users\YourName\.jvr\java_home"
✅ Created JAVA_HOME directory: C:\Users\YourName\.jvr\java_home
✅ jvr initialized successfully!

# Add and use JDKs
$ jvr add jdk21 "C:\Program Files\Java\jdk-21"
$ jvr use jdk21
✅ Now using JDK jdk21 at C:\Program Files\Java\jdk-21
   JAVA_HOME symlink: C:\Users\YourName\.jvr\java_home -> C:\Program Files\Java\jdk-21

Linux/macOS:

# Initialize
$ jvr init ~/.jvr/java_home
✅ Created JAVA_HOME directory: /home/user/.jvr/java_home
✅ jvr initialized successfully!

# Reload shell
$ source ~/.bashrc  # or ~/.zshrc

# Add and use JDKs
$ jvr add jdk21 /usr/lib/jvm/java-21-openjdk
$ jvr use jdk21
✅ Now using JDK jdk21 at /usr/lib/jvm/java-21-openjdk
   JAVA_HOME symlink: /home/user/.jvr/java_home -> /usr/lib/jvm/java-21-openjdk

5.Troubleshooting

5.1."jvr has not been initialized" Error

If you see this error when running jvr use:

❌ jvr has not been initialized. Please run 'jvr init <JAVA_HOME_PATH>' first.

Solution: Run jvr init with a JAVA_HOME path before using other commands:

$ jvr init ~/.jvr/java_home

5.2.Environment Variable Not Updated After Init (Unix)

If JAVA_HOME is not set after running jvr init:

  1. Check if the environment variable was written to your shell config file:

    $ cat ~/.bashrc | grep JAVA_HOME
    # or
    $ cat ~/.zshrc | grep JAVA_HOME
    
  2. Reload your shell configuration:

    $ source ~/.bashrc  # or ~/.zshrc
    
  3. Verify in a new terminal window:

    $ echo $JAVA_HOME
    

5.3.Symlink Creation Failed

If you encounter errors when switching JDK versions:

Windows:

  • Ensure you have administrator privileges or developer mode enabled for creating symlinks
  • Check if the JAVA_HOME directory exists and is writable

Unix:

  • Ensure you have write permissions to the JAVA_HOME directory
  • Check if the target JDK path exists and is accessible

5.4.Permission Denied (Unix)

If you encounter permission errors:

# Check permissions
$ ls -la ~/.jvr/

# Fix permissions if needed
$ chmod 755 ~/.jvr/java_home

Note: It's recommended to use user-level directories (like ~/.jvr/java_home) to avoid permission issues.

5.5.JDK Path Does Not Exist

If you see this error when adding or using a JDK:

❌ JDK path does not exist: /path/to/jdk

Solution: Verify the JDK path is correct and the directory exists:

$ ls -la /path/to/jdk
# or on Windows
$ dir "C:\path\to\jdk"

6.License

Licensed under the Apache License, Version 2.0. See LICENSE for details.

Commit count: 8

cargo fmt