Skip to content

Latest commit

 

History

History
141 lines (115 loc) · 3.81 KB

File metadata and controls

141 lines (115 loc) · 3.81 KB

Using lighty-java

Three operations: find a JRE on disk, install one if missing, run a Java process.

1. Find or install a JRE

use lighty_core::AppState;
use lighty_java::{JavaDistribution, jre_downloader};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    AppState::init("LightyLauncher")?;
    let runtimes = AppState::cache_dir().join("java");

    // 1. Try to find an existing install first
    let java = match jre_downloader::find_java_binary(
        &runtimes,
        &JavaDistribution::Temurin,
        &21,
    ).await {
        Ok(path) => path,
        Err(_) => jre_downloader::jre_download(
            &runtimes,
            &JavaDistribution::Temurin,
            &21,
            |current, total| {
                if total > 0 {
                    println!("{:.1}%", current as f64 * 100.0 / total as f64);
                }
            },
            #[cfg(feature = "events")] None,
        ).await?,
    };

    println!("java: {}", java.display());
    Ok(())
}

find_java_binary uses JavaDistribution::get_fallback so it returns the same path jre_download would have installed — no extra work to correlate the two.

2. Spawn a Java process

use lighty_java::runtime::JavaRuntime;
use tokio::sync::oneshot;
use std::path::Path;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let runtime = JavaRuntime::new("/usr/bin/java".into());

    let mut child = runtime.execute(
        vec![
            "-Xmx2G".into(),
            "-jar".into(),
            "app.jar".into(),
        ],
        Path::new("/tmp"),
    ).await?;

    // Stream output until the process exits or the terminator fires
    let (_tx, rx) = oneshot::channel::<()>();
    runtime.handle_io::<()>(
        &mut child,
        |_data, chunk| { print!("{}",  String::from_utf8_lossy(chunk)); Ok(()) },
        |_data, chunk| { eprint!("{}", String::from_utf8_lossy(chunk)); Ok(()) },
        rx,
        &(),
    ).await?;

    Ok(())
}

handle_io takes function pointers (not closures) so they can be fn-shaped across the Tokio select loop. The data parameter is an opaque context — pass anything you need to share (a logger, an EventBus, …).

3. Subscribe to install events

use lighty_event::{Event, EventBus, JavaEvent};
use lighty_core::AppState;
use lighty_java::{JavaDistribution, jre_downloader};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    AppState::init("LightyLauncher")?;

    #[cfg(feature = "events")]
    {
        let bus = EventBus::new(1000);
        let mut rx = bus.subscribe();
        tokio::spawn(async move {
            while let Ok(event) = rx.next().await {
                if let Event::Java(je) = event {
                    println!("{:?}", je);
                }
            }
        });

        jre_downloader::jre_download(
            &AppState::cache_dir().join("java"),
            &JavaDistribution::Temurin,
            &21,
            |_, _| {},
            Some(&bus),
        ).await?;
    }
    Ok(())
}

The eight JavaEvent variants are listed in events.md.

Distribution fallback

JavaDistribution::get_fallback(version) returns a replacement when the chosen provider doesn't publish a given combo:

Combination Original Fallback chain
Temurin Java 8 on macOS aarch64 Temurin Zulu → Liberica → Temurin
GraalVM Java 11 (any OS) GraalVM Zulu → Liberica → Temurin
Everything else (unchanged)

jre_download and find_java_binary consume that mapping internally, so calling code always sees a working binary path.

See also