# Generated Launchers

Launchers are responsible for starting your application. There are two types of launchers:

![](../images/ui/launchers_type.png)

- **Generated launchers** — install4j can generate native launchers that start your application. For example, on Windows, an .exe file will be created that among other things takes care of finding a suitable JRE, displaying appropriate error messages if required and then starts your application. Using launchers generated by install4j has numerous advantages as compared to using home-grown batch files and shell scripts.   Each launcher definition is compiled separately for each defined [media file](mediaFiles.md). This means that for the majority of all cases, a single launcher definition will be sufficient to start your application. If, for example, your distribution contains two GUI applications and a command line application, you have to define three launchers, regardless of how many media files you define.   When your application is started with a launcher generated by install4j, you can query the system property install4j.appDir to get the installation directory and and install4j.exeDir to get the directory where the launcher resides. Use calls like   System.getProperty("install4j.appDir")   to access these values.
- **External launchers** — If you already have an external launcher for your application, you can let install4j use that launcher instead of generating one. Because external launchers are most likely platform-dependent, you will have to add external launchers for each platform that is targeted by your media files. Make sure to exclude the irrelevant launchers in your media file definitions in this case.  If the launcher is a binary file rather than a shell script, make sure to set its Unix mode in the distribution tree to a value that makes it executable for the owner, such as 755 or 700. This also affects the generated .desktop file whose Exec attribute will start with a shell executable unless the launcher file is executable itself.

### Types of generated launchers

Executables created by install4j can be either GUI applications, console applications or service applications.

![](../images/ui/launchers_executable_info.png)

There is no terminal window associated with a **GUI application**. If stdout and stderr are not redirected on the "Executable info->Redirection" step of the launcher wizard, both streams are inaccessible for the user. This corresponds to the behavior of `javaw(.exe)`.

On Windows, if you launch the executable from a console window, a GUI application can neither write to nor read from that console window. Sometimes it might be useful to use the console, for example, for seeing debug output or for simulating a console mode with the same executable. In that case you can select the Allow -console parameter check box. If the user supplies the -console parameter when starting the launcher from a console window, the launcher will try to acquire the console and redirect stdout and stderr to it. If you redirect stderr and stdout in the "Executable->Redirection" step, that output will not be written to the console.

A **console application** has an associated terminal window. If a console application is opened from the Windows explorer, a new terminal window is opened. If stdout and stderr are not redirected on the "Executable info->Redirection" step of the launcher wizard, both streams are printed in the terminal window. This corresponds to the behavior of `java(.exe)`.

Finally, a **service** runs independently of logged-on users and can be run even if no user is logged on at all. A service cannot rely on the presence of a console, nor can it open windows. On Microsoft Windows, a service executable will be compiled by install4, on macOS a launch daemon will be created and on Unix-like platforms a start/stop script will be generated.

When a service is started, the `main` method of the configured main class will be called. To handle the shutdown of your service, you can use the `Runtime.addShutdownHook()` method to register a thread that will be executed before the JVM is terminated.

For information on how services are installed or uninstalled, see the [help topic on services](services.md).

### Java invocation

The most important configuration of a launcher is done on the "Java invocation" step of the launcher wizard and revolves around replicating the arguments you would pass to the Java launcher in a batch file:

![](../images/ui/launchers_java_invocation.png)

- **VM parameters** — You can provide a fixed list of VM parameters to your launcher and also add version-specific VM parameters. Fixed VM parameters can contain [compiler, launcher and installer variables](variables.md).    Compiler variables are replaced at build time, launcher variables are replaced by the launcher so that the VM sees the replaced value from the very beginning and installer variables are replaced in the main method. This means that using installer variables is not suitable for setting certain kinds of VM parameters like -Xmx, but can be useful for replacing system properties that are only used by your code or by libraries.   See the separate [help topic on VM parameters](vmParameters.md) for more information on the various ways to set VM parameters for launchers.
- **Module or class path** — On the "Java invocation" step of the launcher wizard you can configure both the module path and the class path. These settings correspond to the --module-path and the -cp parameters of the standard Java launcher. The module path is only applicable for Java 9 and higher. Like for the standard Java launcher, you can add directories, single archives or directories with archives. In addition, you can add archives from environment variables and from compiler variables.   The compiler variable entry is useful if the set of JAR files that should be added to the module path or class path is calculated in your build system and these JAR files are not staged to a fixed set of directories that you could reference in install4j. In that case, the the [command line compiler](../cli/compiler.md) as well as the plugins for [Gradle](../cli/gradle.md), [Maven](../cli/maven.md) and [Ant](../cli/ant.md) can set a compiler variable externally where the single JAR files are separated by a configurable separator.
- **Main class** — For Java 9 and higher, you can choose a main class from either the module or the class path. If you choose the module path option, the syntax for the main class is <module name>/<class name> and corresponds to the --module parameter of the standard Java launcher. The chooser dialog shows all the available main classes and inserts the correct value automatically.
- **Arguments** — Like VM parameters, the list of fixed arguments supports compiler, launcher and installer variables. Arguments on the command line are appended to the fixed list of arguments.

### AOT cache

If you select "Create AOT cache on first run" on the "AOT cache" step of the launcher wizard, the launcher passes -XX:AOTCacheOutput=<cache file> to the JVM when the application is run for the first time with Java 25 or higher. The first run serves as a training run and the JVM writes an [AOT cache](https://docs.oracle.com/en/java/javase/25/docs/specs/man/java.html#ahead-of-time-cache) when it exits. On subsequent runs, the cache is passed with -XX:AOTCache=<cache file>, which can significantly reduce the startup time. With Java 24 and lower, no AOT parameters are passed.

By default, the cache is stored in a per-user cache directory: `$XDG_CACHE_HOME/install4j/aot` or `~/.cache/install4j/aot` on Linux and Unix, `~/Library/Caches/install4j/aot` on macOS and `%LOCALAPPDATA%\install4j\aot` on Windows. Below that directory, a subfolder derived from the installation directory is created, so the caches of different applications and of side-by-side installations of the same application never interfere with each other. If you select "Use custom base path for the AOT cache file", you can configure a custom base path in the adjacent text field instead.

The cache file name starts with the launcher ID, followed by a key derived from the application build and the Java runtime, for example `88-17261d03-213b-4bd8-a1c1-5237b839c197-25.0.2-327277132.aot`. Because the key changes when the application or the Java runtime is updated, the cache is always regenerated in that case and never contains stale classes. Cache files of superseded builds are deleted automatically when a new cache is created, so caches do not pile up when you release frequently. With a custom base path, the same cleanup applies to all files that start with the configured base name. When the application is uninstalled, its AOT cache directory is removed as well; this also applies to uninstallations that are performed for an update. With a custom base path, cache files are not removed on uninstallation. To force regeneration manually, delete the cache directory shown above.

During the training run, the system property install4j.aotTraining is set to true. Your application can read it with System.getProperty("install4j.aotTraining"), for example to exercise additional code paths or to delay exit so that the recorded cache covers more of the application. The property is not set on subsequent runs that use the cache.

The cache covers JAR files on the class path and the module path. Classes in directory entries cannot be cached, the compiler prints a warning in that case. If the first run is aborted before the JVM exits normally, no cache is created and the next run tries again. To disable the AOT cache for a generated launcher at runtime, set the environment variable INSTALL4J_NO_AOT_CACHE.

When the cache is created, the JVM prints a few lines about the cache assembly to System.out and System.err. This happens only once per installation and is not visible for GUI launchers and services whose output is redirected.

For archive media files, the AOT cache is disabled by default, because the training run is performed by the first launch of the extracted launcher and its output cannot be hidden. To enable the AOT cache for archive media files as well, select "Enable AOT in archive media files" on the "AOT cache" step of the launcher wizard.

In installers, you can train the cache during the installation instead: add a "Run executable" action that executes the launcher with a quick-exit argument. This only works for per-user installations and requires the application to support an invocation that exits immediately.

### Cross-platform launcher features

Generated launchers optionally support a **single instance mode** on all supported platforms. You can use the [launcher API](../api/launcher.md)to register a startup handler that receives the command line parameters if the launcher is started more than once. In this way, you can handle file associations with a single application instance. GUI launchers on macOS are always in single instance mode because that is a fundamental property of application bundles.

**Icons** for launchers can be generated from a set of PNG files. On Windows, an `.ico` file and on macOS an `.icon` file is compiled, on Linux the generated `.desktop` file references the PNG images. You can also provide pre-built ICO and ICNS files.

To take advantage of the advanced features in macOS 26+ .icon files (created by the Icon Composer app), use the `iconcompiler` command line executable that ships with install4j to create `.icns` and `.car` files from `.icon` files. With a .car file, you glass backgrounds, tintable backgrounds, light and dark variants and transparency effects.

For backward compatibility, you always need a `.icns` file, so no separate entry for the `.car` file is provided. install4j will automatically pick up a `.car` file with the same name next to an `.icns` file.

![](../images/ui/launchers_icon.png)

A **splash screen** image can be configured on the "Splash screen" step of the launcher wizard. The -splash command line parameter does not work for the generated executables, because it is part of the standard Java launchers and not of the Java runtime itself. An exception is the argument -J-splash:none which is emulated by install4j Windows launchers to disable the splash screen from the command. The splash screen supports additional high DPI images with a @2x suffix in the file name.

In addition to the standard splash screen image, install4j allows you to position two lines of text on top of the splash screen image, a version line and a status line. The status line can be updated from your launcher with the [launcher API](../api/launcher.md).

![](../images/ui/launchers_splash_screen_text_lines.png)

If your code loads **native libraries** via `System.load(...)` or if a native library loads dependent libraries, the native library path has to be modified to include the directories where these native libraries are located. In batch or shell scripts you would do this in a platform-specific way, modifying PATH on Windows, DYLD_LIBRARY_PATH on macOS, LD_LIBRARY_PATH on Linux and a variety of other variable names on different Unix variants.

In install4j, you can use the "Java invocation->Native libraries" step of the launcher wizard to specify such directories, and the launcher will take care that the appropriate environment variable is modified. These directories end up in the java.library.path system property in your launcher. If you need different directories for different media files, use a compiler variable for the directory name and override it for each media file.

### JRE search sequence

By default, launchers use the [bundled JRE](jreBundles.md). In case you do not bundle a JRE, the JRE search sequence determines how install4j searches for a JRE on the target system. New configurations get a pre-defined default search sequence.

![](../images/ui/launchers_search_sequence.png)

Apart from searching for previous installations with the same application id, the Windows registry, well-known standard installation locations and paths in environment variables, you can also configure a relative directory in your distribution tree. This is useful if you distribute your own JRE for a launcher that is not provided through a JRE bundle managed by install4j.

install4j has a special mechanism which allows you to bundle JREs with your media files. If you [choose a particular JRE for bundling](jreBundles.md) in one of the [media file wizards](mediaFiles.md), this JRE will always be used first, and you do not need to adjust the search sequence yourself.

If you do not bundle a JRE and a launcher has special Java version requirements that differ from those of the other launchers, you can override them on the "Java invocation->Override Java version" step of the launcher wizard.

If you have problems with JRE detection at runtime, see the [help topic on error handling](../installers/errors.md) for a description on how to get diagnostic information.

### Windows-specific features

A **version info resource** will enable the Windows operating system to determine meta-information about your executable. This information is displayed in various locations. For example, when opening the property dialog for the executable in the Windows explorer, a "Version" tab will be present in the property dialog if you have chosen to generate the version info resource.

The version info resource consists of several pieces of information. If you check Generate version info resource on the "Executable->Windows version info" step of the launcher wizard, there are several fields whose values must be entered. The "original file name", the "company name", the "product name" and the "product version" fields in the version info resource are filled in automatically by install4j and cannot be configured.

![](../images/ui/launchers_windows_version_info.png)

On the "Executable->Windows manifest options" step you can adjust the contents of the executable manifest, a static resource in the executable that controls some Windows features.

![](../images/ui/launchers_windows_manifest_options.png)

With an **execution level** other than "As invoker", you can ask Windows to show a UAC prompt and run the launcher with elevated privileges.

The **DPI awareness** controls whether Windows will scale up pixels in a GUI if high DPI is used. By default, DPI awareness is enabled if the minimum Java version of your project is at least Java 9.

On Windows, executables can be 64-bit or 32-bit. A 64-bit executable can only run with a 64-bit JVM, and a 32-bit executable can only run with a 32-bit JVM. By default, 64-bit executables are generated, but you can switch to 32-bit executables in the "Installer options" step of the Windows media wizard.

### macOS-specific features

By default, the generated application bundle for a GUI application uses the "Executable name" property from the "Executable info" step of the launcher wizard. If you choose compact names as appropriate for Windows and Unix, you may not be happy with the appearance in the Finder on macOS.

On the "Executable info->macOS options" step, you can specify a **localizable application bundle name**. If you specify an i18n variable as the application bundle name, such as ${i18n:myLauncherName}, install4j will name the application bundle directory with the resolved value for the [principal language](localization.md) of your project. In addition, it will take the values for all additional configured languages and set up the appropriate localization in the application bundle.

![](../images/ui/launchers_macos_options.png)

On macOS, file associations and URL handlers are not registered with calls to an API that is provided by the operating system, but by adding special entries to the `Info.plist` file of the application bundle. This is why macOS single bundle archives can handle "Create a file association" and "Register a URL handler" actions at compile-time. By default, associations for all such actions that are contained in the installer configuration on the "Installer->Screens & Actions" step are added to the `Info.plist` file. Optionally, you can choose that only selected actions should be included.

Many advanced behavioral modifications of an application bundle can be done by adding entries to the `Info.plist` file. On the macOS Options step you can specify a fragment that is added to the default `Info.plist` file. For services, this fragment is written to the launcher plist file.

### Modifying launcher shell scripts and secondary start files

Launchers on Unix as well as command line and service launchers on macOS are shell scripts that invoke the standard Java launcher. To include your own modifications, you can specify a fragment that is inserted just before the java invocation.

![](../images/ui/launchers_unix_options.png)

On Linux, two conditions require the generation of additional start files for a launcher and in both cases you can add additional content to them:

- The integration of a GUI launcher into a desktop environment requires the generation of a `.desktop` file. You may want to add additional content to that file to customize the interaction with the desktop environment.
- In the case of a service launcher, a `.service` file is generated if systemd is detected. To configure advanced aspects of systemd execution, you can add additional content to that file.

### Auto-update integration

In the [Installer->Screens & Actions](../beans/screensAndActions.md) step, you can add a "Background update downloader" installer application that runs in the background and automatically downloads an updater installer. Such a background update downloader will not execute the downloaded update installer because that would disrupt the work of the user. Instead, it executes a "Schedule update installation" action to register the downloaded updated installer for later execution.

For GUI launchers, you can select the Execute downloaded updater installers at startup check box in the "Executable info->Auto update integration" step of the launcher wizard. When this GUI launcher is started and a downloaded update installer has been scheduled for installation, the update installer will be executed. By default, the execution mode of the update installer is set to "Unattended mode with progress dialog" with a configurable message.

![](../images/ui/launchers_auto_update.png)

For more on auto-update functionality, see the [corresponding help topic](autoUpdate.md).
