java-manager
A comprehensive Rust library for discovering, managing, and interacting with Java installations.
Features
- Cross‑platform – Works on Windows, macOS, and Linux.
- Java discovery – Find Java via
PATH(quick_search), Everything SDK on Windows (deep_search, requireseverythingfeature), or multi‑strategy full scan (full_search):- Windows: Registry (HKLM + HKCU, including Azul, BellSoft, Temurin, Corretto, GraalVM), keyword BFS, Microsoft Store,
wherecommand, Chocolatey, Scoop, JetBrains bundled JDK. - Linux: walkdir over
/usr/lib/jvm,/usr/java,/opt,/usr/local, plus SDKMAN, JBang, asdf‑vm, JetBrains bundled JDK, Minecraft runtime. - macOS:
/Library/Java/JavaVirtualMachines,/usr/libexec/java_home, plus SDKMAN, JBang, asdf‑vm, Homebrew, JetBrains bundled JDK, Minecraft runtime. - All platforms:
$JAVA_HOMEis always checked first.
- Windows: Registry (HKLM + HKCU, including Azul, BellSoft, Temurin, Corretto, GraalVM), keyword BFS, Microsoft Store,
- Structured metadata –
JavaInfoprovides name, version, vendor, architecture,JAVA_HOME, parsedJavaVersion, and JDK capabilities. - Version matching –
best_match()andfilter_by_version()let you pick the right Java by version requirement ("17","17.0","17.0.2"). - Execution control – Run JARs or main classes with
JavaRunner: classpath, module path,--add-opens/--add-exports, system properties, memory limits, environment variables, working directory, process timeout, I/O redirection with append mode. - TTL caching –
JavaCacheavoids redundant full‑disk scans (default 300 s TTL). - Parallel search – Optional
parallelfeature enables rayon‑powered concurrentJavaInforesolution. - Download – Optional
downloadfeature for async, resumable, parallel‑chunked JDK downloads with automatic extraction (ZIP / tar.gz). - Debug logging – Built‑in
logcrate integration. - Nested JRE dedup – Automatically removes bundled JREs that are sub‑directories of a parent JDK.
Installation
[]
= "0.4"
Or:
Optional features
| Feature | Description |
|---|---|
parallel |
Enables parallel_full_search() via rayon |
download |
Async JDK download with resume, parallel chunks, and archive extraction (ZIP / tar.gz) |
everything |
Use Everything SDK for near-instant Windows search (falls back to full_search on error) |
Usage
Locate Java installations
use ;
// Quick search: look for 'java' in every directory in PATH
let javas = quick_search?;
for java in javas
// Deep search: Everything SDK (Windows, falls back to full_search) or walkdir (Linux/macOS)
let all_javas = deep_search?;
// Full search: registry + BFS + MS Store + where + package managers + IDE paths
let all_javas = full_search?;
// Check JAVA_HOME environment variable
if let Some = java_home
Filter by version requirement
use ;
let javas = quick_search?;
// Best match for Java 17 (highest patch version)
if let Some = best_match
// All Java 11 installations
let java11_installs = filter_by_version;
Cached search
use ;
use Duration;
let mut cache = new;
// First call runs the search, subsequent calls are cached
let javas = cache.get_or_refresh?;
// Force a refresh
let javas = cache.force_refresh?;
Parallel search (requires parallel feature)
use parallel_full_search;
let javas = parallel_full_search?;
Execute a Java program
use ;
let java = java_home.expect;
// Run a JAR file with memory limits and I/O redirection
new
.java
.jar
.min_memory // 256 MB
.max_memory // 1 GB
.arg
.redirect
.execute?;
// Or run a main class
new
.java
.main_class
.arg
.arg
.execute?;
Advanced JavaRunner
use ;
use Duration;
let java = java_home.expect;
new
.java
.jar
.classpath
.add_opens
.add_exports
.system_property
.env
.working_dir
.timeout
.redirect
.execute?;
JDK detection and capabilities
use JavaInfo;
let info = new?;
// Check if this is a full JDK (has javac)
if info.is_jdk
// List available JDK tools
let tools = info.capabilities;
println!;
// e.g. ["javac", "javadoc", "jar", "jlink", "jshell", "jcmd"]
Metadata from a specific Java path
use JavaInfo;
let info = new?;
println!;
println!;
println!;
println!;
println!;
println!;
API Overview
| Function / Method | Description |
|---|---|
quick_search() |
Walks $PATH — fastest, catches the default Java |
deep_search() |
Windows: Everything SDK (requires everything feature, falls back to full_search).Linux/macOS: full_search() |
full_search() |
Registry, BFS, MS Store, where, package managers, IDE paths, JVM directories |
parallel_full_search() |
Same as full_search() but with rayon‑parallel JavaInfo resolution |
java_home() |
Returns the Java pointed to by $JAVA_HOME |
filter_by_version(javas, req) |
Returns installations matching a version requirement |
best_match(javas, req) |
Returns the highest‑versioned match |
JavaCache::new(ttl) |
TTL cache wrapper for search results |
JavaInfo::new(path) |
Create JavaInfo from a path to java or JAVA_HOME |
JavaInfo::matches_version(req) |
Checks version requirement match |
JavaInfo::is_jdk() |
Returns true if javac is present (full JDK) |
JavaInfo::capabilities() |
Returns list of available JDK tools |
JavaInfo::execute(args) |
Run java with shell‑word arguments |
JavaRunner::new() |
Builder for configuring and executing Java programs |
JavaRunner::execute() |
Run the configured program |
JavaRunner builder methods
| Method | Description |
|---|---|
.java(info) |
Set the Java runtime (required) |
.jar(path) |
Set the JAR to execute |
.main_class(name) |
Set the main class to execute |
.classpath(paths) |
Set classpath (-cp) |
.module_path(path) |
Set module path (--module-path) |
.add_opens(m, p, t) |
Add --add-opens flag |
.add_exports(m, p, t) |
Add --add-exports flag |
.system_property(k, v) |
Set -Dkey=value |
.min_memory(bytes) |
Set initial heap (-Xms) |
.max_memory(bytes) |
Set max heap (-Xmx) |
.arg(val) |
Add a program argument |
.env(key, val) |
Set environment variable |
.working_dir(path) |
Set working directory |
.timeout(duration) |
Kill process after timeout |
.redirect(redirect) |
Set I/O redirection |
JavaRedirect methods
| Method | Description |
|---|---|
.output(path) |
Redirect stdout to file (truncate) |
.error(path) |
Redirect stderr to file (truncate) |
.input(path) |
Redirect stdin from file |
.append_output() |
Append to stdout file instead of truncating |
.append_error() |
Append to stderr file instead of truncating |
Version requirement syntax
req |
Matches |
|---|---|
"17" |
Any Java 17 (major == 17) |
"17.0" |
Any Java 17.0.x |
"17.0.2" |
Exact version 17.0.2 |
Search Strategy Details
full_search() attempts multiple discovery strategies on each platform:
| Platform | Search locations |
|---|---|
| Windows | $JAVA_HOME → Registry (HKLM+HKCU for JavaSoft, Azul, BellSoft, Temurin, Corretto, GraalVM) → BFS on all drives → Microsoft Store → where java → Chocolatey → Scoop → JetBrains IDE bundled JDK |
| Linux | $JAVA_HOME → /usr/lib/jvm → /usr/java → /opt → /usr/local → SDKMAN → JBang → asdf‑vm → JetBrains bundled JDK → Minecraft runtime |
| macOS | $JAVA_HOME → /Library/Java/JavaVirtualMachines → ~/Library/Java/JavaVirtualMachines → /usr/libexec/java_home → SDKMAN → JBang → asdf‑vm → Homebrew → JetBrains bundled JDK → Minecraft runtime |
Nested JRE deduplication: When both a JDK and its bundled JRE are
discovered (e.g. jdk-xxx/jre/bin/java.exe), only the JDK-level installation
is kept. Standalone JREs are unaffected.
deep_search() fallback: On Windows, when the everything feature is
enabled and the Everything SDK is not available (service not running / not
installed), deep_search() automatically falls back to full_search(). Without
the everything feature, deep_search() always delegates to full_search().
Debug Logging
Enable logging to see what the library is doing behind the scenes:
RUST_LOG=debug
This will output scan paths, registry keys checked, stale entries skipped, and version parsing results.
License
This project is licensed under the MIT License. See the LICENSE file for details.