Convert Java to EXE
Why, When, When Not and How
Last update: 23-Jul-2014
This article is also available in: Deutsch
By Dmitry LESKOV
If you are sure you need a real EXE, go straight to AOT Compilers.
"How do I make an .EXE file from my Java application?", "Need help converting
jar to exe", "Is it possible to create a Windows executable using Java?" —
these and similar questions are among the most popular topics on Java developer forums.
Should you start such a topic today, you are likely to
encounter the following three types of replies:
- "You cannot"
- "You should not, because that would kill the very purpose of Java"
- "You can do that with third party software X and Y"
The truth is that there exist two completely different approaches to the
creation of native executables from Java applications, addressing different
sets of problems. Moreover, under certain conditions some of those problems
may be solved without making an EXE.
So the most correct way to reply to such a post
would be a request for more information,
namely what is the goal of conversion to EXE.
And the most frequent answer would be
Simplify Java Application Deployment
Java compiles to platform-independent bytecode (.class files), which
is not directly supported by PC hardware. So a Java program needs
a Java Runtime Environment (JRE) to run, which would either interpret
the bytecode instructions or compile them to native code on the fly.
This in turn means that the author of that program has to ensure
somehow that a proper version of the JRE is present on each end user
In a general case you may not expect that your end users will know
what a JRE is, how to check its version, and how to download and install it.
This is especially true for consumer applications, such as games or
And those who already have a JRE installed may not like the idea of
installing a different version, because it may break their existing
Java applications and favorite applets.
Then, even if you can make sure that the right version of the JRE is properly
installed on all enduser systems, which is quite possible in a classroom or
enterprise environment, the command line required to launch your
Java application can be quite long:
java -Xmx200m -cp whatever.jar -Dsome.property MyApp
Yes, you may put that line into a batch file and call it
but it looks so much easier to give your program to a friend, teacher or
colleague as a single file that can be run by a double-click. Or, even better,
enable it to be installed and uninstalled in a native manner without
affecting other applications.
So it comes as no surprise that the primary motivation for seeking a way
to convert a Java application into an EXE file is to make its deployment
and use simpler and safer for an average user, that is, a Windows user.
What surprises newbie Java developers is that the JDK does not offer
such functionality (except for JavaFX applications - see below.)
Before J2SE 1.4, all you could make with JDK tools were
No need to use any third-party tools
Single distribution for all Java-enabled platforms
Application will not start on systems that do not have a JRE
Application will not work if it uses APIs absent in the default JRE
Need to teach users that .JAR files are clickable
JAR File Specification
You can make your Java application runnable via a double-click by
packaging it into a so called executable jar. You do that by
specifying the main class of your application, any extra jar files
it may require and so on in the jar's manifest file
Then you use the
jar utility from the Java SDK to package
your classes and resource files, specifying the
and the name of your manifest file:
jar cvfm MyApp.jar MyApp.mf *.class *.gif
This will result in the creation of
MyApp.jar. Now, if you type
java -jar MyApp.jar
the Java launcher will read the manifest from
main method from the class
Moreover, if you double-click that jar file on a system that has JRE
installed, the java launcher will be invoked automatically.
Note: Jar files are associated with the
javaw launcher on Windows, which does not open a console on
startup. If your application needs a console,
write a batch file which would start it using the
If your application consists of more than one jar file, there is
an open source tool called One-JAR that claims to correctly
repackage multiple jars into one.
The major problem with executable jars is compatibility.
The default JRE may be of an older version than is required by your application
or may not have the necessary Java Optional Packages (previously known as
Standard Extensions) installed.
For instance, if your app uses any of the latest and greatest JDK 8
features, it will not work on JRE 7 or any prior version.
Fortunately, back in the day Sun Microsystems had created a Java application deployment
technology that eliminates this compatibility problem and adds some nice features.
It has been part of the Java platform since version 1.4 and is called
Java Web Start
Java Web Start (JWS)
and the underlying Java Network Launch Protocol (JNLP)
enable Java application delivery from a standard Web server.
The end user initiates application installation by clicking on an URL.
If the Java Web Start engine is not present on the system, the user
is prompted to download and install it. Once Java Web Start is in place,
clicking on the same URL will initiate the application download and
installation procedures. It may involve download and installation of the
required version of the JRE and Optional Packages.
Upon their successful completion, the application
is launched. The application will be cached on the user's system so next
time the user clicks on the same URL, the JWS engine will launch the
local copy of the application from the cache, if it detects that the
computer is offline or the application was not updated on the Web site.
Another important feature of JWS is its ability to run your application in
a sandbox - a restricted container based on Java security
architecture. But, unlike an applet, your application can gain access
to local system resources like the filesystem, printer and system clipboard
using the JNLP API even if it comes from an untrusted environment,
after prompting the user for confirmation.
Java Web Start is included in the normal Oracle JRE (not in the Server JRE),
with plugins for popular browsers, though some browser configuration tweaks may be
The JavaFX Packager
tool can in particular prepare JavaFX applications for deployment via Java Web Start.
There are also third-party implementations of
the JNLP protocol, some of them also include tools that assist you in
the creation and maintenance of JNLP packages.
That was the bright side. Now, what is not so good about JNLP?
First off, for seamless operation both the browser and the Web server
that hosts the JNLP-enabled application must support
application/x-java-jnlp-file MIME type. Some hosting providers
do not support it. Moreover, versioning and incremental updates require
additional support from the Web server, which has to be implemented
using servlets, cgi-bin scripts, etc.
On the client side, a major browser would be configured to recognize
the above MIME type during installation of the JWS engine, but users of
less popular browsers, such as Opera, may have to do that manually.
JNLP-enabling an application may involve minor changes in its code and
(re)packaging it into a set of jar files.
Before J2SE 5.0, JWS had very little to offer in terms of desktop integration -
all it could do was create a desktop icon and/or a Start Menu entry for the
application. On Windows, the application will not show up in
Add/Remove Programs, so end users would have to run the Java Web Start
application manager in order to remove your application.
Finally, JWS user interface needs polishing.
Many users complained about ugly windows with incomprehensible messages.
To sum it up, JWS can be a viable option in a controlled environment,
such as corporate intranet, but it is not ready for the consumer market,
where you may be better off using
Custom Java Launchers And Wrappers
When a Java program is invoked using one of the methods discussed above
(batch file, executable jar, or Java Web Start/JNLP), the operating system
runs a Java launcher from the JRE. The Windows version of the JRE has
separate launchers for command-line and GUI apps, called
As a result, all running Java applications have the same Taskbar/Alt-Tab
icons and appear in the Windows Task Manager as either
javaw.exe. If you have two or more Java apps running, you
have no means to distinguish between multiple instances of the standard
Java launcher in the Task Manager.
In fact, those launchers are just small native programs that load
the Java Virtual Machine from a DLL/shared library and then feed
your program to that JVM using the Invocation API.
That API is part of the
Java Native Interface (JNI),
so it is standardized, and it is also very simple. This makes it relatively
easy to write your own launcher with a unique name and icon.
What it has to do is find a suitable
JRE on the end user's system
(unless you bundle the JRE with your application),
load and initialize the JVM, and run your application on it.
If you do not have the right tools, skills, or time to develop a custom launcher
for your Java application, there are quite a few third-party Java launcher
generators listed in the Tools section of the frame.
(It is the most frequently updated section of this article —
it seems to me that Java developers just LOVE to reinvent this particular wheel.)
Some of them provide additional features such as instant
splash screen, stdout and stderr redirection, and so on,
the most notable being wrapping.
A Java wrapper is essentially a custom Java launcher that is also
a self-extracting archive containing
all the application's classes, jars and auxiliary files.
The wrapper unpacks those files on startup and removes on termination.
This way, your application is distributed as a single executable.
A wrapper normally looks up the JRE upon startup. If the JRE is not present
or its version does not match the application's compatibility requirements,
some wrappers may install the JRE (if you have included it when wrapping your
application) and/or download and install the required version of the JRE.
The most sophisticated wrappers may also setup file associations and create
shortcuts on first run. But if you need something more complex, such as
support for automatic updates or uniform cross-platform deployment,
have a look at
Java-Aware Setup Authoring Tools
If all you need is install a private copy of the JRE alongside your
application and create shortcuts that run your application on that JRE,
you may use any setup generator. However, using a Java-aware tool may give you the
- Install-time JRE detection and download
- Generation of native launchers
- User-editable JVM parameter files
- Redirection of stderr and stdout for saving logs and exception stack traces.
- Registration of Java applications as Windows services and Unix daemons
This category is the most diversified in terms of tool pricing and
functionality. The differences are explained below by example.
Windows-centric tools, such as
Advanced Installer for Java
enable you to build MSI (Windows Installer) packages.
Multi-platform tools can generate native installers for multiple platforms —
Windows, Linux, Mac OS X, as well as RPMs and tarballs.
is one such tool. Again, specifically for JavaFX applications you can use
which is capable of producing MSI, DMG, RPM, and DEB packages.
There exist also Java-based setup authoring tools
enabling you to create cross-platform installations,
Those installations are essentially executable jars
with platform-specific logic selected at run time.
is perhaps the most well known tool of this type,
but if its pricing is beyond your budget, consider the free-with-restrictions
which can do both native and cross-platform installers,
or the open source IzPack.
Finally, there is One Tool to Rule Them All -
which can create both Windows desktop (MSI) and cross-platform
installations, plus server and mobile ones,
for any type of application and for a multitude of platforms.
And yes, it does support JRE lookup and bundling, native launchers, and so on.
For straightforward installations, however, InstallShield is an overkill.
Also note that InstallAnywhere and InstallShield are aimed at the
enterprise developer and are priced accordingly.
All the above solutions do not change the fundamental
principle mentioned in the first section of this article.
Whether you make an executable jar or create a sophisticated installer,
your Java program is still deployed as platform-independent bytecode.
In the early days of Java, the only way to execute a Java program on a common
PC hardware was to interpret that bytecode.
Today, any decent Java implementation includes a Just-In-Time (JIT) compiler
that compiles frequently executed methods to native code.
So it sounds quite natural to take one step further and compile the entire
application down to native code before it is deployed.
Such tools exist and they are called
AOT compilers are known also as "static compilers" and
"native code compilers". The latter term is
the most used and, as it often happens, the least correct from the
technical standpoint, because JIT compilers also produce native code.
An Ahead-Of-Time (AOT) compiler takes as input your jars and class files and
produces a conventional native executable for the target platform, such
as Windows EXE or Linux ELF binary. Just like any other technical solution,
this has its advantages and drawbacks.
Performance. A JIT compiler works at application's runtime and shares
CPU and memory resources with the application that it compiles and possibly other
applications. An AOT compiler runs on the developer's system with no resource
or compilation time constraints. Therefore it can potentially use more powerful
resource-intensive optimizations, yielding better code.
This advantage is amplified
if you application will be deployed
to embedded systems or low-end desktop PCs, where the JIT compilers
simply may not have enough resources to work.
Intellectual Property Protection. Java bytecode is very easy to decompile - just
"download java decompiler" and you will get your source code back in 5 minutes.
Yes, you may obfuscate the
names of public classes and methods that are not accessed via reflection or JNI,
but excessive control flow obfuscation can render your bytecode unverifiable on future JVMs
and hinders the JIT compiler's ability to
Finally, encrypting your Java bytecode does not protect it at all
regardless of the encryption algorithm you use.
In contrast, native code produced by an optimizing AOT Java compiler
is about as hard to reverse engineer as if you had coded the original program in C++.
Needless to say, there is no performance loss.
If you are concerned about protecting your intellectual property, have a closer look
at native compilation.
User Perception. Java client applications often suffer from the so called
warm-up cycle syndrome. Starting up a Java application
involves bytecode interpretation, profiling and JIT-compilation. So Java programs
tend to start much longer than their native counterparts and the initial response
time of a complex GUI element, such as a grid or a tree view, is much worse than after
it has been used several times,
which are the two major reasons for Java still being perceived as slow by many users.
A native executable runs directly on hardware, without the interpret-profile-compile
overhead, so it may start faster and immediately demonstrates the best response times.
Native deployment. Even the most sophisticated
Java-aware setup tools have to generate native launchers
for better desktop integration, and those launchers may also need to download and
install the JRE.
Executables produced by an AOT Java compiler do not depend on the JRE
and can be deployed using any setup authoring tool available for the target platform.
Moreover, AOT compilers may come with specifically tailored setup generators that
create compact, professional installers.
Dynamic applications. Classes that the application loads dynamically at
run time may be unavailable to the application developer. These can be third-party
plug-ins, dynamic proxies and other classes generated at runtime and so on.
So the runtime system has to include a Java bytecode interpreter and/or a JIT compiler.
Moreover, in the general case only classes that are loaded by either system or
application classloader may be precompiled to native code. So applications that use
custom classloaders may only be partially precompiled, unless the AOT compiler
and runtime are aware of those specific classloaders' behavior.
Eclipse RCP applications may be fully compiled
despite all but a few hundred startup classes being loaded by OSGi classloaders.
It is also possible to compile
Web applications running on Apache Tomcat.
Hardware-specific optimizations. A JIT compiler has a potential advantage
over AOT compilers in that it can select code generation patterns according to
the actual hardware on which the application is executing. For instance, it may use
the latest SSE instruction set to speedup floating point calculations.
An AOT compiler must either produce code for the lowest common denominator or apply
versioning to the most CPU-intensive methods, which may result in code size
Java bytecode had been originally designed for compactness,
so it has a much higher level than a typical CPU instruction set and
takes less space than the equivalent machine code for a real-world general purpose
processor, such as Intel x86. But Java class files contain not only code.
The amount of symbolic information in Java class files has grown dramatically
over the years due to the development of numerous APIs and their package
structure. So now there is
not much difference in disk footprint between the original and AOT-compiled
forms of an application, and the download size can be even
smaller than the size of the JRE.
There is also a common misconception that AOT compilation kills Java portability.
This is not the case, because the source code need not be changed, so
you can always deploy your application as bytecode to a platform for which you
do not have an AOT compiler. (That would of course blow the benefit of IP
There used to be half a dozen AOT Java compilers on the market in the year 2000,
but the only two that have survived are
Excelsior JET and
GCJ (GNU Compiler for Java).
You will find a side-by-side comparison of these products
in the Bonus Features section below.
RoboVM is an interesting new
open-source project that enables you to compile Java code down to native iOS
executables. However, it uses the Android standard library, not Java SE,
so you only get portability between iOS and Android.
If you are in the embedded field, check out
which targets J2ME CDC and also has limited support for J2SE 1.3.
This concludes the main part of the article. I update it regularly, so
if you have any comments or know of any resource/tool URLs which I should have added,
please send them to me.
Please also do not hesitate to contact me
if you need help in optimizing, protecting and/or deploying your Java applications.
AOT Compilers Comparison
I work for the company that makes Excelsior JET, so
skip this section
if you believe it is going to be a shameless plug.
- Target platforms
As of July 2014, the official
GCJ Status page
lists 15 supported targets, from "bare metal" ARM and XScale to IBM s390x mainframes.
Some of the targets, most notably Windows, are not fully supported, though.
Excelsior JET supports Windows and Linux on 32‑ and 64‑bit x86.
The 32‑bit Windows version has been on the market since the year 2000,
the Linux one joined it in 2004, so both are quite mature by now.
The 64‑bit versions, first released in 2013, are catching up.
Update 23-Jul-2014: Starting from version 10,
Excelsior JET is also available for OS X,
so now it supports all major desktop operating systems.
- Standard compliance
GCJ has not passed the Oracle's official
Java Compatibility Kit (JCK) test suite and is quite far from even
attempting to do that. The major reason is that the
GCJ runtime library, libgcj, is an open source clean-room
implementation of the core Java API classes,
and thus was way behind Sun developments even before the Oracle takeover.
At the moment GCJ may only compile graphical applications built using
third-party AWT-independent GUI toolkits, such as
libgcj is being slowly merged with GNU Classpath.
The unofficial compatibility testing results for GNU Classpath
claim that it includes most, but not all of the JDK 1.4 API features as of Sep 2007 (the last time the tests were run.)
Note however that the data used to back that claim is not being produced by running
the JCK, so they can only confirm availability, not compatibility
of the respective APIs.
Excelsior is a
Java Authorized Licensee,
and its product uses the licensed Oracle's implementations of the Java SE API.
Excelsior JET has passed the JCK and is
certified Java SE 7 Compatible
on a number of Windows and Linux platforms.
Java 8 support is in the works.
Update 23-Jul-2014: Excelsior JET 10 has also passed the Java SE 7 JCK
on OS X.
- Dynamic class loading
Both products support dynamic class loading.
The GCJ runtime runs dynamically loaded classes on an interpreter, whereas the
Excelsior JET runtime features a JIT compiler.
- Deployment facilities
GCJ is just a compiler; you are responsible
for choosing a third-party deployment tool and setting it up for packaging
of the executables GCJ produces.
Excelsior JET includes a toolkit that enables you to create
Windows and Linux installers, or integrate easily with third-party setup generators.
You may also compile your Java applications into Windows services.
GCJ and libgcj are open source (GPL) and therefore can be freely
downloaded, modified and distributed. Note that 'libgcc exception' applies to libgcj,
so linking with it does not by itself cause your program
to fall under the GPL.
Commercial use Excelsior JET licenses
start from $1,500 per developer, with substantial
available to early stage startups and other very small companies.
Authors of freely downloadable non-commercial Java programs can
apply for a free license.
Deployment to general purpose desktops and
servers is royalty-free, but runtime fees apply if you deploy your
application to embedded systems
or bundle it with devices that provide dedicated functionality.
Mr. Andrew Fedoniouk has pointed my attention to his past project called
that aimed at enabling the creation of Java GUI apps that would run without any JRE.
It was essentially a combination of the
and a small GUI API, which could be packaged together with your application class files
into a sub-one-megabyte executable.
If you know of any other interesting attempts to get rid of the JRE, please
send them to me.
Java App As A Single EXE
In this blog post, I show how you can, using just a couple of free tools, package your Java app as a single EXE requiring no installation.
Optionally, add Excelsior JET to the mix to reduce your app's disk footprint, improve its startup time, and protect
your code against reverse engineering.
Creating a Distribution Package of Your Java Application
A practical guide to double-wrapping a Java application into a
native Windows launcher and installer using ANT, NSIS, ProGuard, and Launch4j,
all free tools. Note: The original Web site is 410 Gone, the link points to the
most recent snapshot available from the Internet Wayback Machine.