Home > Articles > Programming > Java

Java Reference Guide

Hosted by

Toggle Open Guide Table of ContentsGuide Contents

Close Table of ContentsGuide Contents

Close Table of Contents

Launch4j

Last updated Mar 14, 2003.

If youโ€™re looking for more up-to-date information on this topic, please visit our Java article, podcast, and store pages.

I have often heard the question, "how can I run my Java program as a Windows executable?" If you search the Web on this topic, you'll find commercial and open source solutions as well as strong opinions on both sides of the "Java running native on Windows" polarity. On the pro-Windows side, the argument is that it can be too difficult for non-geeks to launch Java applications and on the anti-Windows side, the arguments are typically "why bother?" or a diatribe on the benefits of platform independence.

I called the argument a polarity for a reason: both poles have their merits and the optimal solution is a blending between the two. I am personally opposed to solutions that attempt to convert all classes and dependencies (libraries typically packaged as JAR files) as well as a JRE into a single executable file. There may be performance improvements (arguable), but there are too many things that can go wrong when writing applications from a pure Java perspective, such as when using dynamic class loading or other extendable architectures. So as not to discount the topic altogether, there are times when a native executable is desirable, such as when integrating a Java application into a native framework or simply providing Windows users a happy "EXE" file to click on.

The solution that I propose is the creation of a native process that finds a JRE and launches a Java class. With the strategy, both viewpoints can be satisfied: the Windows user has a familiar entry-point into the Java application, but without disrupting the integrity of the Java environment. In this article I discuss the creation of a native Windows executable using the open source project launch4j.

Introduction

While I have faced this problem in the past, my current motivation behind building a Windows launcher for my Java applications began with an exploration into "portable applications". Portable applications are applications designed to run on a portable device, such as on a USB thumb drive. The purpose of using portable applications is to enable you to move from computer to computer, with only your portable device, and bring your applications and data with you. For example, if you use Thunderbird as your email client, you not only want to bring the Thunderbird application with you, but you also want to bring all of your email. In this way you can work on a computer from your thumb drive without disrupting the computer and not worrying about leaving any of your data behind.

After purchasing an 8GB Patriot USB drive from eCOST.com, I downloaded a set of applications from PortableApps.com. The PortableApps Suite includes open source products such as Mozilla Firefox, Mozilla Thunderbird, GIMP, OpenOffice, VLC Media Player, Audacity, and more. As a user of all of these products I thought it was a great idea and began looking at how to integrate my Java applications into PortableApps and quickly learned that the PortableApps menu builds its menu dynamically by finding Windows executables in subdirectories below the "PortableApps" directory. That obviously presented a problem to me that could only be solved by creating a native Windows launcher file.

launch4j is an open source project available for download from SourceForge.net that presents itself as, "a cross-platform tool for wrapping Java applications distributed as jars in lightweight Windows native executables." It provides the capabilities to wrap a JAR file in an EXE or to simply create an EXE that finds a JRE and launches a Java application. It provides robust support for control over the CLASSPATH and environmental configuration options, such as heap settings and other JVM options, and it can be configured and run from a Swing GUI or it can be launched automatically by an Ant task. And as version 3.0 is being released and the project is almost four years old, it is a project that you can trust.

Building an executable with launch4j

As of this writing, the latest version is 3.0.0-pre2 and can be downloaded here. The easiest way to install launch4j is to download the win32 executable and launch it. Walk through the installation script and then launch the launch4j GUI. This presents the screen shown in figure 1.

Figure 1

Figure 1: Launch4j Basic Tab

The example that I am going to use in this article is my pure Java Music Player, named "JBox". JBox is packaged in a JAR named "JBox.jar" and has a slue of dependencies, such as JDOM, JoSQL, JLayer, an MP3 tag library reader, and so forth. Its icons are stored externally in JPG files and its configuration is maintained in an XML file, so it is simple in organization, but includes enough complexity to stretch the capabilities of launch4j. The deployment directory structure is defined as follows:

  • lib: this folder contains all application and dependency JAR files
  • icons: this folder contains all JPG images that the application uses for icons (at some point later they should be incorporated into another JAR file)
  • conf: this folder contains the XML configuration file for the application (held in a separate directory for later expansion)

Figure 1 shows the initial display when you launch launch4j, namely the basic tab. The first text box specifies the output file to generate. In this example, the JBox source code and build directories are contained in my "C:\projects\JBox" folder and then I build the aforementioned deployment directory structure in a "deploy" subdirectory. Therefore I set the target executable file to "C:\projects\JBox\deploy\JBox.exe".

The JAR file that contains the JBox class is located in the lib folder's JBox.jar file, hence the "Jar runtime path" is defined to be ".\lib\JBox.jar".

The "Don't wrap the jar, launch only" checkbox allows you to differentiate between the launching strategy I am proposing of a thin executable that launches a Java application and the conversion of your JAR file to an executable file. By checking this checkbox, you are telling launch4j to create a launcher only, not to include any Java classes in the executable.

The "Icon" text box allows you to associate an icon with your executable. If you do not have the facilities to create an ".ico" file, GIMP (available as a portable application) can convert a JPEG file to a Windows icon file for you (using the "File" -> "Save As" functionality).

Finally, I found it necessary in my tests to set the "Change dir" text field to the current directory, ".". This may be a bug in launch4j because the default behavior, if a "Change dir" value is not specified, is to set the working directory to that of the executable file. The real purpose of this text box is for the executable to change directories to a relative directory within your application to act as the "current working directory" for your application. Adding a "." to this field is an easy workaround, so I won't complain too loudly.

Hovering over the different text boxes will display usage information about each text box, so fill in values as appropriate for your application. When you're finished, click on the "Classpath" tab, which I have shown in figure 2.

Figure 2

Figure 2: Launch4j Classpath Tab

The "Classpath" tab defines two important components:

  • The main class to execute in your application. In this example, the JBox class is contained in the com.javasrc.jbox.JBox class.
  • A list of CLASSPATH elements

If your application is not self-contained within a single JAR file, meaning that it needs additional JAR files or directories in its CLASSPATH, then click on the "Custom classpath" check box and define the CLASSPATH. The CLASSPATH elements are defined either in absolute directories or in relative directories to the "current working directory". In the sample application, all of the application and dependency JAR files are contained within the lib folder. You can click on the "New" button to create a new entry, type its path in the "Edit item" text box, and press "Enter" to add it to the CLASSPATH. If you need to change the order of the CLASSPATH elements, click on an item in the list and press the up or down arrow buttons.

The header tab contains a list of Windows components used during the linking phase of the executable file (recall that native applications require compilation and then linking with system libraries before constructing an executable.) You typically do not need to change anything on this tab, so we'll skip it and move on to the "JRE" tab, shown in figure 3.

Figure 3

Figure 3: Launch4j JRE Tab

The "Emb. JRE Path" defines the JRE path relative to the executable, or an absolute path. For now we'll leave this blank and rely on the underlying environment to already have an appropriate JRE installed. The "Min JRE version" text box defines the minimum requirements for the JRE required to launch the application and must be defined in the form:

X.X.X[_xx]

You are likewise permitted to define a maximum JRE version if there are known incompatibilities with your application and later JREs.

The initial and maximum heap sizes define the JVM options "-Xms" and "-Xmx", respectively. Remember that if you do not specify a maximum heap size, then your heap can only grow to the maximum size supported by the operating system (which in the case of Windows is a maximum heap size of 64 megabytes), so if you need more memory, this is the place to specify it. In the example I defined an initial heap of 16 megabytes that can climb up to 256 megabytes.

The "JVM Options" text box allows you to define any number of JVM options. For example, in this case I defined that the default look and feel for the application should be the "Windows look-and-feel", by defining the system property (-D) "swing.defaultlaf".

The "Set env. variables" tab, shown in figure 4, allows you to define any operating system environment variables that your application may need.

Figure 4

Figure 4: Launch4j "Set env. variables" Tab

If your application has a splash screen that you want to display when it launches, you can specify that image file in the "Splash" tab, shown in figure 5.

Figure 5

Figure 5: Launch4j "Splash" Tab

I am somewhat opposed to specifying a splash screen here and delegating that responsibility to the Windows executable file because that behavior would need to be somehow replicated in non-Windows environments. Instead I would suggest that you build the splash screen functionality into your Java applications directly. I covered building splash screens in my first book, Java 2 From Scratch (QUE, 1999), but if there is interest I can publish similar content here in the Java Reference Guide.

Windows executables can optionally display a set of versioning information, which can be specified in the "Version Info" tab, shown in figure 6.

Figure 6

Figure 6: Launch4j "Version Info" Tab

File version must be of the form:

X.X.X.X

But you are free to add any version information in the "Free form" text boxes that you want. The remainder of this dialog is pretty self-explanatory, but remember that this information is optional.

Finally, you are permitted to display custom messages when errors occur in the "Messages" tab, shown in figure 7.

Figure 7

Figure 7: Launch4j "Messages" Tab

When you are finished, click on the save button (the third icon on the toolbar that looks like a 3.5" floppy disk.) If you have any errors, they will be displayed at this point, and you need to resolve them before you are permitted save your file. Finally, click on the "Build wrapper" toolbar icon (right next to the save icon, it looks like a gear.) The "Log" message at the bottom of launch4j shows the status of the build (which is very fast) and will include "Successfully created: " on success.

Test your executable and enjoy!

Integrating launch4j into Ant

In the last installment we used the launch4j GUI to build an executable file to launch a Java-based MP3 player. While the GUI was helpful in configuring the options we wanted to incorporate into the executable, integration of the launch4j functionality into an automated build is more desirable. Otherwise, after routine builds complete, we would need to manually open launch4j and generate our executable.

Luckily launch4j can be executed in an Ant build script using a custom launch4j Ant task. It takes as input an XML file describing how to build the executable file, which, not coincidentally, is the format of the file generated by the launch4j GUI application. Thus we can use the launch4j user interface to generate an XML file that can be used in our automated build script.

The GUI provides a nice wrapper around the XML file, but before continuing, let's review the components of the XML file. Listing 1 shows the contents to my launch4j.xml file.

Listing 1. launch4j.xml

<launch4jConfig>
 <dontWrapJar>true</dontWrapJar>
 <headerType>gui</headerType>
 <jar>.\dist\lib\JBox.jar</jar>
 <outfile>.\dist\JBox.exe</outfile>
 <errTitle></errTitle>
 <cmdLine></cmdLine>
 <chdir>.</chdir>
 <priority>normal</priority>
 <downloadUrl>http://java.com/download</downloadUrl>
 <supportUrl></supportUrl>
 <customProcName>false</customProcName>
 <stayAlive>false</stayAlive>
 <icon>C:\projects\JBox\deploy\icons\music.ico</icon>
 <classPath>
  <mainClass>com.javasrc.jbox.JBox</mainClass>
  <cp>.\lib\JBox.jar</cp>
  <cp>.\lib\gentlyWEB-utils-1.1.jar</cp>
  <cp>.\lib\javasrcutil.jar</cp>
  <cp>.\lib\jd3lib.jar</cp>
  <cp>.\lib\jdom.jar</cp>
  <cp>.\lib\jl1.0.jar</cp>
  <cp>.\lib\jlfgr-1_0.jar</cp>
  <cp>.\lib\JoSQL-1.0.jar</cp>
  <cp>.\lib\xerces.jar</cp>
 </classPath>
 <jre>
  <path>..\..\java\jre</path>
  <minVersion>1.5.0</minVersion>
  <maxVersion></maxVersion>
  <dontUsePrivateJres>false</dontUsePrivateJres>
  <initialHeapSize>16</initialHeapSize>
  <maxHeapSize>256</maxHeapSize>
  <opt>-Dswing.defaultlaf=com.sun.java.swing.plaf.windows.WindowsLookAndFeel</opt>
 </jre>
 <versionInfo>
  <fileVersion>1.0.0.0</fileVersion>
  <txtFileVersion>1.0</txtFileVersion>
  <fileDescription>JBox Music Player Portable</fileDescription>
  <copyright>(c)2007 JavaSRC. All Rights Reserved.</copyright>
  <productVersion>1.0.0.0</productVersion>
  <txtProductVersion>1.0</txtProductVersion>
  <productName>JBox Music Player Portable</productName>
  <companyName>JavaSRC</companyName>
  <internalName>JBox</internalName>
  <originalFilename>JBox.exe</originalFilename>
 </versionInfo>
</launch4jConfig>

The things that I changed between the previous section and this one are the destination EXE file to ".\dist\JBox.exe" and the source JAR file to ".\dist\lib\JBox.jar" to match my build script and I changed the location of the embedded JRE to "..\..\java\jre", but more on that later. This XML file is divided into the following sections:

  • Header: I am grouping the first several entries into a header category because they do not have too much in common. This section includes our option to not wrap our JAR file inside an EXE (<dontWrapJar>), the header type is GUI, the location of the source JAR file and destination EXE, the icon file for the EXE, and so forth.
  • Classpath: this section lists all of the JAR files or directories to add to your CLASSPATH at run time. Note that launch4j is not compiling your source code, so this is not a list of JAR files for compilation. This list includes the locations of all JAR files when the application launches. In this example, all JAR files will be located in a lib directory located directly under the resultant EXE file. This section also includes the name of the main class for the EXE to launch.
  • JRE: this section specifies information about the location and characteristics (such as minimum and maximum JRE versions) of the JRE that will be used to launch the main class of the application. If you leave the path blank then the EXE will pick up the first JRE that it can find that meets your criteria (the version is between the minimum and maximum specifications), but in this case I have specified that there will be a specific JRE located two directories above the EXE in the java/jre directory. I will discuss this more next week, but as a sneak preview, this is part of my portable application integration.
  • Version Info: this section defines the version and copyright information that will be embedded into the EXE

For more information about the XML file, take a look at the online documentation.

With this XML file built, Ant integration is a very straightforward procedure. Ant integration is typically performed in two steps:

  1. Import an Ant task
  2. Call the Ant task inside of one of your targets

Launch4j includes an Ant task that is implemented by its net.sf.launch4j.ant.Launch4jTask class. In order to import this Ant task, you need to include two of its JAR files: launch4j.jar and xstream.jar, which are located in the launch4j installation directory hierarchy. If you installed launch4j from the installation file on Windows then the default installation location is: "C:\Program Files\Launch4j". Therefore, to import the launch4j Ant task, add the following snippet to your Ant build script:

<property name="launch4j.dir" location="C:/Program Files/Launch4j" />
<taskdef name="launch4j" 
     classname="net.sf.launch4j.ant.Launch4jTask"
     classpath="${launch4j.dir}/launch4j.jar:${launch4j.dir}/lib/xstream.jar" />

The taskdef Ant command defines a new task that is implemented by the specified "classname". In this case we included the two required JAR files in the CLASSPATH to satisfy the task definition. All that is left is to execute the launch4j Ant task inside one of our targets. In its simplest form, the launch4j task accepts a sole "configFile" attribute that references the launch4j.xml file that we created earlier. Thus the following snippet creates a new "exe" target that exercises the launch4j task:

<target name="exe" description="Use launch4j to generate an EXE for JBox" depends="dist" >
 <launch4j configFile="./launch4j.xml" />
</target>

In this example, my launch4j.xml is in the same directory as my build.xml file. Again, the instructions on how to build the executable are all contained in the launch4j.xml file. The Ant task allows you to embed the entire contents of the launch4j.xml file, but doing so precludes you from using the GUI to edit it. On the other hand, there are a handful of common options that you can override in the task itself. Namely when building an EXE you might want to change versioning information to match your build. Thus the following attributes can be added to the launch4j task:

  • jar
  • jarPath
  • outfile
  • fileVersion
  • txtFileVersion
  • productVersion
  • txtProductVersion
  • bindir
  • tmpdir

The majority of these attributes allow you to change the version information to be embedded in your executable for your build. This is a good place to add the specific build number, which may already be in your build script.

Portable Java Applications

I have spent a considerable amount of time in the past few articles discussing the process of building a Windows executable to launch your Java applications. While this is a good feature in and of itself, there is a specific application of this technology that inspired me to dedicate time to it: portable applications.

A portable application, simply put, is an application that runs on a portable device, such as a USB drive. The challenge in converting a standard application to a portable application is in both removing its environmental dependencies as well as redirecting its own resource requests to the portable device. For example, a Windows application may need libraries that may not be available on the host system or the application may store information in the user's home directory. The application needs to be packaged with its dependencies and then configured to store its stateful information on the portable device.

The premier source for open source applications configured to run on a portable device is PortableApps.com. PortableApps combines the best in open source applications, including Mozilla Firefox and Thunderbird, GIMP, FileZilla, Audacity, MPlayer, VLC Player, OpenOffice, and a dozen other titles that you can review here. The benefits to installing PortableApp's suite of products are two-fold: the applications have been preconfigured to run on a portable device and it includes a menu application that automatically discovers portable applications and adds "start menu"-like functionality that can be launched from your Windows system tray.

Java applications provide a distinct advantage, which is also its greatest limitation in providing support for portable applications. Because Java applications run inside a Java Virtual Machine, the only system dependency that a Java application has is the Java Virtual Machine itself (you can easily include dependent JAR files on the portable device.) Thus, as long as you can bundle a Java Runtime Engine with your application, you do not need to be concerned with Windows system dependencies. The challenge is that the Java Runtime Engine is large, the JRE that I extracted from Java SE 6 was almost 80 megabytes.

The good news is that USB drives are becoming more and more affordable. If you search eCOST.com for "USB Flash Drive" and review the "Storage" results, you will find a 4GB or 8GB flash drive for well under $100. At the time of this writing I bought a Patriot Memory 8GB drive that, after rebates, was less than $70. In order to run Java applications from a USB drive you will need plenty of space, and I would not recommend using anything under one gigabyte of storage, although it is technically possible.

In this article I demonstrate how to integrate a Java application into PortableApps using launch4j and then propose a strategy to help you deploy multiple Java applications to a portable device while minimizing their overall footprint on the drive.

Before we begin, you will need to obtain a portable device and install the PortableApps suite on it. You can download PortableApps from the following URL:

http://portableapps.com/suite

There are three download options:

  • [lb] Standard Edition: this installation includes the PortableApps menu as well as the most common portable applications, including Firefox, Thunderbird, and OpenOffice. They claim it runs comfortably on a 512MB flash drive.
  • [lb] Lite Edition: for the more conservative flash drive, this edition substitutes AbiWord in place of OpenOffice and runes comfortably on a 256MB flash drive.
  • [lb] Base Edition: the version includes the PortableApps menu application as well as the directory hierarchies so that you can customize the applications you want installed

Depending on the applications you use and the size of the flash drive you have choose the most appropriate installation. Launch the installation file and point it to your portable device. You can add additional applications to PortableApps by downloading the installation file from the PortableApps web site and then clicking on the "Options" button (on the right) and choosing "Install a New App". You can manually install it, but this method ensures that everything is installed in the correct location and it causes the PortableApps menu to refresh itself automatically.

After you've had time to peruse your portable applications, let's review the requirements for building an application compatible with PortableApps. The directory structure that PortableApps creates on your portable device is as follows:

Documents   \Music
   \Pictures
   \Video
PortableApps   \PortableAppsBackup
   \PortableAppsMenu
   \{One directory for each portable application}
StartPortableApps.exe

In order to add a new application to the PortableApps menu, you need to create a new directory in the "PortableApps" directory and include an executable file for the PortableApps menu to launch (it only launches EXE files, which is why we need launch4j to create an EXE for us.) But before building an EXE as we did in the last couple articles, we need to consider the footprint of a JRE on our portable device. Although portable devices are becoming cheaper and storage space is increasing, it does not mean that we should abuse it by using unnecessary space. As mentioned previously, the JRE included with the Java SE 6 is approximately 80MB, so it would be in our best interest to reuse a single JRE for all of our applications.

Fortunately, one of the features of launch4j is that you can specify the absolute or relative directory of the JRE to use to launch your application. Thus I propose the following solution: create a "java" folder in the root of your portable device and create a "jre" subfolder that contains the JRE to use when launching your application. Furthermore, I propose that we include a "lib" folder to contain commonly used JAR files. So the final directory structure will look like this:

Documents   \Music
   \Pictures
   \Video
PortableApps   \PortableAppsBackup
   \PortableAppsMenu
   \{One directory for each portable application}
   \MyJavaApp
     MyJavaApp.exe
java   \jre
   \lib
StartPortableApps.exe

By now I am sure that you have a JRE installed somewhere on your computer, but if not then download one from java.sun.com. The default installation location for both JREs as well as JDKs (which you can use in this case too) is "C:\Program Files\java\jdk|jre version number", for example:

C:\Program Files\java\jre1.6.0_01

Copy the contents of this folder, which will include a "bin" and a "lib" folder to the jre folder of your portable device. In the end you should have the following directory on your portable device:

java   \jre
     \lib
     \bin
   LICENSE
   LICENSE...

Now we need to build an EXE that uses this JRE. Recall from the last article that the script that controls how an EXE is built is contained in an XML, named launch4j.xml by default. My launch4j.xml file for the JBox Music Player is shown in listing 2.

Listing 2. launch4j.xml

<launch4jConfig>
 <dontWrapJar>true</dontWrapJar>
 <headerType>gui</headerType>
 <jar>.\dist\lib\JBox.jar</jar>
 <outfile>.\dist\JBox.exe</outfile>
 <errTitle></errTitle>
 <cmdLine></cmdLine>
 <chdir>.</chdir>
 <priority>normal</priority>
 <downloadUrl>http://java.com/download</downloadUrl>
 <supportUrl></supportUrl>
 <customProcName>false</customProcName>
 <stayAlive>false</stayAlive>
 <icon>C:\projects\JBox\deploy\icons\music.ico</icon>
 <classPath>
  <mainClass>com.javasrc.jbox.JBox</mainClass>
  <cp>.\lib\JBox.jar</cp>
  <cp>.\lib\gentlyWEB-utils-1.1.jar</cp>
  <cp>.\lib\javasrcutil.jar</cp>
  <cp>.\lib\jd3lib.jar</cp>
  <cp>.\lib\jdom.jar</cp>
  <cp>.\lib\jl1.0.jar</cp>
  <cp>.\lib\jlfgr-1_0.jar</cp>
  <cp>.\lib\JoSQL-1.0.jar</cp>
  <cp>.\lib\xerces.jar</cp>
 </classPath>
 <jre>
  <path>..\..\java\jre</path>
  <minVersion>1.5.0</minVersion>
  <maxVersion></maxVersion>
  <dontUsePrivateJres>false</dontUsePrivateJres>
  <initialHeapSize>16</initialHeapSize>
  <maxHeapSize>256</maxHeapSize>
  <opt>-Dswing.defaultlaf=com.sun.java.swing.plaf.windows.WindowsLookAndFeel</opt>
 </jre>
 <versionInfo>
  <fileVersion>1.0.0.0</fileVersion>
  <txtFileVersion>1.0</txtFileVersion>
  <fileDescription>JBox Music Player Portable</fileDescription>
  <copyright>(c)2007 JavaSRC. All Rights Reserved.</copyright>
  <productVersion>1.0.0.0</productVersion>
  <txtProductVersion>1.0</txtProductVersion>
  <productName>JBox Music Player Portable</productName>
  <companyName>JavaSRC</companyName>
  <internalName>JBox</internalName>
  <originalFilename>JBox.exe</originalFilename>
 </versionInfo>
</launch4jConfig>

The important thing to notice in this script is that the path of the JRE is defined to be "..\..\java\jre", or looking at our directory structure again:

PortableApps   \JBox
     JBoxPortable.exe
java   \jre

The path goes from JBoxPortable.exe to the JRE that we just copied to "java\jre". Now when we execute this script (see the two previous articles in this series), the resultant EXE is configured to use this specific JRE. Create a directory in the PortableApps directory and copy this EXE to it, including the required JAR files, and then either restart the PortableApps menu or choose "Options" and then "Refresh App Icons" and you should see your executable file. Figure 1 shows a screenshot of the PortableApps menu with my "JBox Music Player Portable" running in it.

Figure 193

Figure 193. PortableApps menu with JBox Music Player Portable

Summary

Launch4j allows you to create Windows executables that launch your Java applications. In the first article I presented a step-by-step example that created an executable using the launch4j graphical user interface. In the next article I reviewed the underlying XML file that drives launch4j and look at how to integrate launch4j into an Ant script for the automated generation of a Windows executable. And in this article, I demonstrated how to deploy your Java applications to a portable device using the PortableApps.com, including a shared JRE to conserve precious space on a portable device.