GraalVM compiles Swing programs

When the Swing program uses exe4j to generate executable files, the startup of large files is slow and cannot meet product-level requirements. The executable file packaged through GraalVM’s native-image tool is about 45M, and the startup time is basically controlled to the millisecond level.

The Swing runtime uses some JNI and reflection classes. The static analyzer cannot predict all reachable codes and requires us to provide some metadata information. Manually editing metadata is troublesome and error-prone. GraalVM provides a native-image-agent tool to collect these class information and save it to reflect-config.json, jni-config.json, resource-config.json, proxy-config.json, serialization-config.json and predefined -classes-config.json These 6 json format configuration files. Of course, if you are familiar with the libraries or classes you need to use, you can also write these files manually.

1. Create Swing project

A Java project was created directly through IDEA. In order to facilitate the creation of executable jar packages, Maven support was added. We create a minimalist GUI program, which generates the following interface after startup:

2. Packaging executable JAR

There are two optional ways, create a Maven project directly through IDEA; or create the project first, right-click on the project and select “Add Framework Support” and select “Maven” to convert the project into a Maven project.

Here we choose maven-shade-plugin and configure the following content in your Maven configuration file:

<?xml version="1.0" encoding="UTF-8"?>
<project>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.randy.graalvm</groupId>
    <artifactId>swing</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.5.1</version>
                <configuration></configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>com.company.SwingDemo</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

After executing mvn package to complete the packaging, the following file will be generated. Double-click to run it to confirm that it has been packaged correctly.

3. Collect metadata

The Swing program uses some code that cannot be identified through static analysis (such as JNI). The java command line parameter-agentlib provided by GraalVM helps us collect metadata.

Here we use swing-1.0.jar to practice the process of collecting metadata.

3.1 Setting environment variables

Make sure the java command uses GraalVM

set GRAALVM_HOME=D:\Programs\GraalVM
set PATH=D:\Programs\GraalVM\bin
3.2 Run JAR program

This jar file is an executable jar packaged by Maven. Execute the jar file with the following command, click on each function, and ensure that all required classes are loaded.

java -cp swing-1.0.jar -agentlib:native-image-agent=config-output-dir=d:/tempDir com.company.SwingDemo

As shown in the command line, the collected metadata will be saved under d:/tempDir.

4. Copy metadata to jar

Place the configuration file under META-INF/native-image/${groupId}/${artificatId}, as shown below:

After the copy is completed, use the mvn package command to regenerate the executable jar.

5. Generate executable file

native-image -jar swing-1.0-SNAPSHOT.jar

Commonly used configuration items when building native-image

Configuration items

describe

-H: + ReportExceptionStackTraces

Show exception stack trace during build

–no-fallback

Build a native image that does not depend on JVM or show build failure

–allow-incomplete-classpath

Allow building with incomplete classpath, this parameter is suitable for libraries that rely on weak references

-H:ConfigurationFileDirectories=native-image

Configure the configuration file directory address of the collected meta information

-H: +AddAllCharsets

Supports all character sets

–report-unsupported-elements-at-runtime

Report unsupported methods and fields only when running the native image instead of reporting errors during the build

–enable-url-protocols=https,http

Supported URL protocols. Failure to add this parameter will result in inability to access the web address.

The execution log is as follows. Through the log, you can see that there are a total of 8 steps in the construction. Even our simplest program takes 2 minutes.

6. Copy fontconfig.bfc

The contents of the directory after the construction is completed are as shown in the figure below. The program can be started through swing-1.0-SNAPSHOT.exe.

Unfortunately, the current swing-1.0-SNAPSHOT.exe cannot run successfully. When running through the cmd command line, I received the following error:

Until I added the following code in the first line of the main method of the program to set the java.home attribute

System.setProperty("java.home", ".");

After recompiling and executing it again, it still failed, but there was an error, the font was wrong.

I copied lib/fontconfig.bfc in the Java installation directory into the compilation result. The final directory looks like this

The final running result is as follows

7. Remove console

At this point, the above executable file can be executed correctly, but there is an additional command line window behind it, through the editon tool

editbin /subsystem:windows swing-1.0-SNAPSHOT.exe

window output

At this point, we have got an exe file that can be executed correctly without any redundant command line windows.