One of the advantages of Java version 9 and above is that it enables us to build a native installer using its new module system. This means that the modules can be linked into a native executable file that can run on Windows Mac OS and Linux. This is not an executable in the sense that is in pure native code, uninterpreted, as was once possible for code compiled using GCJ in the GNU GCC project, but still, it simplifies installation of programs written in Java in the sense that it removes doubt about the Java runtime required by installing a slim, suitable Java interpreter.
I'll demonstrate this by building a very simple application in Windows that lists all the charsets available on the system. Open cmd.exe and change into the temp directory with
cd %TMP%
We are going to use THIS Java source:
package com.technojeeves.charsets;

import java.nio.charset.Charset;

import java.util.Map;
import java.util.SortedMap;

public class CharsetLister {
    public static void main(String[] args) {
        SortedMap<String, Charset> cs = Charset.availableCharsets();

        for (Map.Entry<String, Charset> e : cs.entrySet()) {
            System.out.printf("%s=%s%n", e.getKey(), e.getValue().toString());
so save it into the current directory. We can begin by creating a module-info file:

 Make module source

Let's compile that Java source file and the file:

 Compile java source and module

We can now create a module using the class files now in our output directory ('charsets'):

Create the module

So we now do the packaging. The --dest argument tells us where we want the installer to end up, and here we want an MSI type of installer. We need to specify that the program will be a console program we want to be able to choose the installation directory and we point the installer at the module using the --module-path and we tell the packager which module and main class we want to form the executable. 

As you can see, if we list the 'jpk' directory we see the finished installer.

Package the code

We can run the installer and install the software:

Install the software

Let's temporarily set the PATH variable so we can run the software as an installed program. You would normally do this as a permanent thing by setting the PATH through System in Environment Variables.

Now we've done that, we can run it using its executable name of CharsetLister(.exe). We here reduce the output by constraining it to contain only those entries with the substring "IBM".

Temporarily set PATH to run from command line