21

I've watched a few online presentations that briefly mentioned self-contained applications in Java 9, but I have a question that I would like cleared up.

With the new module system, you're now allowed to only include the minimum amount of code required to run your application. However, does the system that wishes to run the application still require the JRE, or is that something that can be included in the base module within the program?

I suspect it's the latter, as the page (here) to download the newest version of Java still shows version 8_151.

TL;DR - Using Java 9, is it possible to create a self-contained executable that can be executed on a system without the JRE/Java installed?

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Jacob G.
  • 28,856
  • 5
  • 62
  • 116
  • 1
    java always (at least for the latest versions for sure) allowed packets to be packaged with a specific JRE. With the modular system of java 9, the volume of data you need to include is simply reduced. In previous releases this was achieved with profiles. – mr mcwolf Oct 21 '17 at 07:05
  • 1
    FYI, besides the two good Answers about `jlink` and `javapackager`, you will find background info in [*Java Client Roadmap Update* of 2018-03](https://www.oracle.com/technetwork/java/javase/javaclientroadmapupdate2018mar-4414431.pdf) and [*Java Is Still Free*](https://medium.com/@javachampions/java-is-still-free-c02aef8c9e04). – Basil Bourque Mar 31 '19 at 00:42

3 Answers3

14

jlink

Yes, this is possible with jlink (JEP 282), but all of your code and your dependencies need to be modular JARs (i.e. ones with module-info.class). It works like this:

jlink
    --module-path $JAVA_HOME/jmods:mods
    --add-modules your.app
    --launcher launch-app=your.app
    --output your-app-image

In detail:

  • --module-path lists the folders that contain modules - this needs to include the platform modules shipped with the JDK you want to use (in $JAVA_HOME/jmods) and your application modules (mods)
  • --add-modules names the module(s) that you want your runtime image to contain - all of its (their) transitive dependencies are included
  • --launcher is optional, but very handy; it creates an OS-specific launcher (e.g. a .bat on Windows) with the given name (launch-app) that launches the specified module (your.app; in this case assuming the main class is defined for it)
  • --output specifies where to create the runtime image
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Nicolai Parlog
  • 47,972
  • 24
  • 125
  • 255
  • It is also interesting how `jlink` is different to `javapackager` in terms of what you can do to create a self-contained application. Any chance you can update your answer to include information about `javapackager` too? – ZhekaKozlov Oct 21 '17 at 07:24
  • 1
    the launcher can also be a native executable file. for windows this is a better solution than the bat file because it can also include resources as an app icon. – mr mcwolf Oct 21 '17 at 07:26
  • @ZhekaKozlov I've never used `javapackager` and would have to research it. Why don't you write an answer about that one? :) – Nicolai Parlog Oct 21 '17 at 08:36
  • @Nicolai Because I haven't used it as well – ZhekaKozlov Oct 21 '17 at 09:54
  • Thank you very much for the detailed answer! This will definitely change embedded systems as we know it. – Jacob G. Oct 21 '17 at 22:45
  • 4
    According to the new [`javapackager`](https://docs.oracle.com/javase/9/deploy/self-contained-application-packaging.htm#JSDPG583) page, it uses `jlink` internally. So for a real self-contained application with executables, use javapackager. – Mordechai Oct 22 '17 at 00:44
  • 2
    Recent releases (i.e. Java 14+), replaced the javapackager tool mentioned in comments on this question with a new tool named [jpackage](https://openjdk.java.net/jeps/392) which "Supports native packaging formats to give end users a natural installation experience", unlike jlink, it supports packaging for both modular and non-modular applications. – jewelsea Feb 02 '22 at 08:20
11

jpackage:

As an edit (pointed in comments), javapackager was removed from JDK in Java-10 and one can look forward to making use of jpackage as an incubating tool since Java-14.

javapackager

You can use javapackager tool.

The Java packaging tools provide built-in support for several formats of self-contained application packages.

The basic package is a single folder on your hard drive that includes all application resources and the JRE. The package can be redistributed as is, or you can build an installable package (for example, EXE or DMG format.)

Though there are certain restrictions associated with building these applications with javapackager which includes -

  • Self-contained application packages must be explicitly requested by passing the native argument to the Ant task or javapackager -deploy command.

  • Self-contained application packages must be built on the operating system on which it is intended to run. Prerequisite tools must be available to build a package in a specific format.

  • Self-contained application packages can only be built using JDK 7 Update 6 or later. The Java Packager for JDK 9 packages applications with a JDK 9 runtime image. To package a JDK 8 or JDK 7 JRE with your application, use the JDK 8 Java Packager.


One way to create a basic self-contained application is to modify the deploy ant task:-

<fx:deploy width="${javafx.run.width}" height="${javafx.run.height}"
           nativeBundles="all"
           outdir="${basedir}/${dist.dir}" outfile="${application.title}">
    <fx:application name="${application.title}" mainClass="${javafx.main.class}"/>
    <fx:resources>
        <fx:fileset dir="${basedir}/${dist.dir}" includes="*.jar"/>
    </fx:resources>
    <fx:info title="${application.title}" vendor="${application.vendor}"/>
</fx:deploy>

Native packages can be built using the javapackager command tool. Java Packager Command to Generate Self-Contained Application Packages would be something like -

javapackager -deploy -native -outdir OUTPUT_DIR -outfile APPLICATION_NAME 
    -srcdir PACKAGE_SRC_DIR -srcfiles APPLICATION.jar -appclass MAIN_CLASS
    -name "YourApplication" -title "SelfContained"
Naman
  • 27,789
  • 26
  • 218
  • 353
0

This worked for me. It includes JRE in the application folder and creates an executable file. I had my file java files in the src folder and this command compiled and created a dist folder with an executable file.

javapackager -makeall -name WordAnalyzer_app -appclass queue.Gui
pause
Aman Singh Rajpoot
  • 1,451
  • 6
  • 26