> For the complete documentation index, see [llms.txt](https://jbundle.avelino.run/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://jbundle.avelino.run/comparison/vs-jpackage.md).

# jbundle vs jpackage

They solve different problems.

## Quick Summary

| Tool         | Purpose                 | Output                       |
| ------------ | ----------------------- | ---------------------------- |
| **jbundle**  | Native-feeling binaries | Single executable            |
| **jpackage** | Traditional installers  | .exe, .msi, .dmg, .deb, .rpm |

## jpackage: Distribution via Installers

**jpackage** is included in JDK 14+. It creates platform-specific installers:

* Windows: `.exe`, `.msi`
* macOS: `.dmg`, `.pkg`
* Linux: `.deb`, `.rpm`

The workflow is traditional:

```
User downloads installer → Runs installer → App installed to system → Launch from menu
```

jpackage bundles a full JVM runtime, but that's where optimization ends. No startup improvements, no runtime tuning. It's essentially "take your JAR, wrap it with a JVM, generate an installer."

**Best for:** Desktop applications where users expect traditional installation.

## jbundle: Native-Feeling Binaries

**jbundle** creates a single executable binary. The workflow mirrors Go or Rust:

```
Download → chmod +x → Run
```

No installer. No installation step. No system directories. The binary is self-contained — move it anywhere, copy to a server, distribute via curl.

**Best for:** CLI tools, microservices, serverless functions.

## Detailed Comparison

| Aspect                   | jbundle                       | jpackage                     |
| ------------------------ | ----------------------------- | ---------------------------- |
| **Output**               | Single executable             | Platform installers          |
| **User experience**      | Download → run                | Download → install → run     |
| **JVM size**             | Minimal (\~30-50MB via jlink) | Full JDK (\~300MB)           |
| **Startup optimization** | AppCDS, CRaC, profiles        | None                         |
| **Distribution**         | curl, cp, scp                 | App stores, package managers |
| **System integration**   | None                          | File associations, shortcuts |
| **Target audience**      | Developers, DevOps            | End users                    |

## Why Startup Time Matters

The JVM is notorious for slow startup. A simple "hello world" can take 500ms+. For CLI tools or short-lived processes, this is unacceptable.

jbundle attacks this from multiple angles:

### 1. Minimal Runtime (jlink)

Instead of the full JDK (\~300MB), jbundle uses `jdeps` to detect which modules your app uses, then `jlink` to create a minimal runtime (\~30-50MB). The runtime is created without internal compression and then compressed once at maximum level in the final binary — avoiding double-compression overhead. Less code to load = faster startup.

### 2. AppCDS (Class Data Sharing)

On first run, the JVM generates a shared archive with pre-parsed class metadata. Subsequent runs load this cache directly, cutting startup by 60-75%.

### 3. Profile-Specific JVM Flags

The `--profile cli` option configures the JVM for short-lived processes:

* C1-only compilation (skip C2)
* SerialGC (simpler, faster startup)
* Reduced code cache

Result: \~200-350ms startup for CLI tools.

### 4. CRaC (Coordinated Restore at Checkpoint)

On supported JDKs, jbundle can create a checkpoint of your warmed-up app. Subsequent runs restore in 10-50ms — essentially native binary territory.

## When to Use What

### Use jpackage when:

* Building desktop applications with GUIs
* Users expect traditional installation
* You need system integration (file associations, shortcuts)
* Distributing through app stores

### Use jbundle when:

* Building CLI tools
* Building microservices or serverless functions
* You want Go/Rust-style distribution
* Startup time matters
* Deploying to servers or containers

## tl;dr

* **jpackage** = installers for desktop apps
* **jbundle** = native-feeling binaries with optimized startup


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://jbundle.avelino.run/comparison/vs-jpackage.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
