Operations 8 min read

How to Turn Your Java Swing App into a Standalone Executable (No JRE Needed)

This article compares five Java packaging methods—GraalVM, JLink, Exe4J, batch scripts, and plain JAR—detailing their pros and cons, then introduces a custom WinForm tool that bundles Swing applications into self‑contained executable files, complete with code examples and deployment steps.

macrozheng
macrozheng
macrozheng
How to Turn Your Java Swing App into a Standalone Executable (No JRE Needed)

I mainly develop with Java and enjoy creating small Swing utilities, but Swing apps require a JRE to run, which limits distribution.

Current Java program packaging options include:

Use the popular GraalVM to compile a JAR into a native executable.

Use JLink to package the JAR into a native executable.

Generate a launcher with Exe4J and create a self‑extracting archive.

Create a batch script and wrap it in a self‑extracting archive.

Distribute only the JAR, requiring users to install a JRE and launch via command line.

The above options have different advantages and disadvantages:

Technology

Advantages

Disadvantages

GraalVM

Performance boost, lower resource consumption, high security

Long build time, difficult debugging, limited reflection support

JLink

Binary file, lighter than bundling full environment

Complex build, difficult debugging, large size

Exe4J

Lower entry barrier, better user experience, easier debugging

Large size, requires JRE at runtime, not suitable for small tools

Batch script

Lower entry barrier, flexible configuration, easy updates, easy debugging

Large size, requires JRE, not suitable for small tools

Plain JAR

Small distribution, easy updates

Cannot run on machines without JRE, requires command‑line launch, high entry barrier, poor user experience

Because binary distribution is hard to debug and JAR distribution harms user experience, I combined these approaches and built a WinForm packaging tool to convert Java programs into native executables. The tool UI is shown below:

Software usage:

This may be a useful open‑source project , the mall project is a SpringBoot3 + Vue e‑commerce system (60K stars on GitHub) with a micro‑service architecture, Docker and K8s deployment, covering front‑end store, back‑end admin, and full order workflow.

Boot project: https://github.com/macrozheng/mall

Cloud project: https://github.com/macrozheng/mall-swarm

Tutorial site: https://www.macrozheng.com

Project demo:

Below is a sample Swing program.

pom.xml file:

<code><?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.helloswing</groupId>
  <artifactId>HelloSwing</artifactId>
  <version>1.0-SNAPSHOT</version>

  <properties>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <!-- https://mvnrepository.com/artifact/com.formdev/flatlaf -->
    <dependency>
      <groupId>com.formdev</groupId>
      <artifactId>flatlaf</artifactId>
      <version>3.5.1</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>3.7.1</version>
        <configuration>
          <!-- Get all project dependencies -->
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
          <!-- Remove jar-with-dependencies suffix -->
          <appendAssemblyId>false</appendAssemblyId>
          <!-- Specify main class -->
          <archive>
            <manifest>
              <mainClass>org.hellloswing.HelloSwing</mainClass>
            </manifest>
          </archive>
        </configuration>
        <executions>
          <execution>
            <id>make-assembly</id>
            <!-- Bind to package phase -->
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>
</code>

HelloSwing.java file:

<code>package org.hellloswing;

import com.formdev.flatlaf.FlatDarkLaf;
import com.formdev.flatlaf.FlatLightLaf;
import javax.swing.*;
import java.awt.*;

public class HelloSwing {
    public static void main(String[] args) throws UnsupportedLookAndFeelException {
        // Initialize look and feel
        FlatLightLaf.install();
        UIManager.setLookAndFeel(new FlatDarkLaf());
        // Initialize window
        JFrame jFrame = new JFrame("Hello Swing!");
        // Set size
        jFrame.setSize(500, 500);
        // Close operation
        jFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        // Center window
        jFrame.setLocationRelativeTo(null);
        // Set components
        JPanel jPanel = new JPanel(new BorderLayout());
        jPanel.add(new JLabel("Hello Swing!", JLabel.CENTER), BorderLayout.CENTER);
        jFrame.getContentPane().add(jPanel);
        // Show window
        jFrame.setVisible(true);
    }
}
</code>

After building a fat JAR, export a trimmed JRE, then use the packaging tool to bundle the JAR and JRE into an EXE file, which can be run by double‑clicking.

JavapackagingGraalVMSwingExecutableJLinkWinForm
macrozheng
Written by

macrozheng

Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.