Windows installer for a Java app, from jpackage to Setup.exe
Use jpackage to bundle your JAR with a Java runtime into a folder with a native .exe, then wrap that folder in a Windows installer, no WiX toolset required.
Updated October 31, 2026 · 3 min read
"Download Java first" is not something you want to tell customers. Since JDK 14, jpackage solves half the problem: it bundles your application with a trimmed Java runtime and gives it a native MyApp.exe. The other half, a Windows installer, is where jpackage asks you to install the WiX toolset and learn its quirks. This guide takes the folder jpackage produces and turns it into a Setup.exe without any of that.
Step 1: build the application image
Put the runnable JAR and its dependency JARs in one folder (lib/ below), then run jpackage on Windows:
jpackage --type app-image --name MyApp --input lib --main-jar myapp.jar --main-class com.example.Main --icon app.ico --app-version 2.4.0
This creates MyApp/, containing:
MyApp.exe, a native launcher with your icon;app/, your JARs and a configuration file;runtime/, a Java runtime with only the modules the app needs.
For a JavaFX app, add --module-path pointing at the JavaFX SDK's lib folder and --add-modules javafx.controls,javafx.fxml (adjust to the modules you use). For a modular app, use --module instead of --main-jar.
Open MyApp\MyApp.exe to confirm the app starts without a system Java installed. The runtime/ folder is what makes that work.
jpackage must run on Windows to produce a Windows image. A Windows machine, a virtual machine, or a Windows runner in CI all work; see building on a Mac for options.
Step 2: zip the image
Zip the contents of MyApp/: MyApp.exe, app/ and runtime/. Keep the structure; the launcher expects app/ and runtime/ beside it.
Step 3: build the installer
- Upload the zip to ExeTup. It picks
MyApp.exeas the main program. - Enter the name, the same version you gave
--app-version, and your publisher name. - Choose all users (Program Files, admin prompt) or current user (no prompt). Java business apps distributed to employees often go per user; consumer apps usually per machine.
- Keep 64-bit; jpackage builds for the JDK's architecture, which is x64 on nearly every machine.
- Upload
app.ico, enable the shortcuts, and build.
The result is a Windows installer that puts the application image in place with a Start Menu entry and an uninstaller. Customers never see Java.
Why not let jpackage make the installer?
jpackage --type exe or --type msi does produce an installer, and for some teams it is enough. It needs WiX Toolset 3 installed and on the PATH, offers a fixed wizard with limited options, and its uninstaller and shortcut behaviour has rough edges that are hard to change without digging into WiX. Using the app-image and a separate installer keeps the two concerns apart: jpackage does the runtime bundling it is good at, and the installer does the Windows integration.
Java-specific notes
- Runtime size. A trimmed runtime is 40 to 80 MB.
jlink-style module trimming happens automatically;--jlink-options --strip-debugand--jlink-options --no-man-pagestrim a bit more. - Java options. Pass JVM flags with
--java-options "-Xmx1g"at image build time; they are baked into the launcher's configuration. - Updates. Ship a new installer with a higher version. Installing over the previous version replaces
app/andruntime/in place. - Launch4j and similar wrap a JAR in an
.exebut don't bundle a runtime by default, so they don't remove the "install Java" step. jpackage does. - Signing. Sign
MyApp.exebefore zipping and the downloadedSetup.exeafterwards; see the SmartScreen guide.
FAQ
Do customers need Java installed?
No. The runtime/ folder jpackage creates contains everything the app needs, and the installer ships it with the app.
Can I install the app without the WiX toolset?
Yes. WiX is only needed for jpackage's own exe and msi types. Build an app-image instead and use ExeTup for the installer.
Does this work with JavaFX?
Yes. Include the JavaFX modules when building the image, test MyApp.exe, then package the folder as above.
Can I bundle a different JDK, such as Temurin?
jpackage uses the JDK it runs from for the runtime. Run it from the JDK you want to ship, or pass --runtime-image with a runtime you built with jlink.
Related guides
- How to make a Setup.exe for your Windows app (no code)What a Setup.exe actually does, the three ways to make one, and how to turn an app folder into a professional installer in minutes without writing an installer script.
- Turn an .exe into a Windows installer (exe to Setup.exe)How to convert a plain .exe, or a folder with an .exe in it, into a real Windows installer with shortcuts and an uninstaller, without writing an installer script.
- Create a Windows installer for a .NET app (WPF, WinForms, console)Publish a .NET desktop app with dotnet publish, choose between framework-dependent and self-contained, then wrap the publish folder in a Setup.exe with shortcuts and an uninstaller.