Von Dr. Cassian Holt, Testing & Performance Engineering bei Java Fleet in Essen-Rüttenscheid
📚 Was bisher geschah – GraalVM-Serie
Bereits veröffentlicht:
- ✅ Teil 1: Der heilige Graal – Warum AOT-Kompilierung für Java spannend ist.
- ✅ Teil 2: Native Images – Wo Java schnell wird – Grundlagen, Build-Pfade, erste CLI-Beispiele.
- ✅ Teil 3: Enterprise Production – Build-Pipelines, Reachability-Metadata, CI-Hinweise.
Heute: Teil 4 zeigt End-to-End, wie wir eine Java-Swing-App als Native Image bauen – macOS, Linux, Windows.
⚡ Kurze Zusammenfassung – Das Wichtigste in 30 Sekunden
Wir bauen eine kleine Java-Swing App (JFrame, Icon, Menü) und erzeugen dafür ein Native Image.
Du bekommst: ein minimales Projektgerüst, eine pom.xml mit GraalVM Native Build Tools für Maven, OS-Voraussetzungen, Ressourcen-Einbindung (Icons, Properties), Reflection/Agent-Workflow für Spezialfälle, sowie Troubleshooting.
Build-Kommando: mvn -Pnative -DskipTests package – fertig ist das GUI-Binary pro OS.
Hi, Java-Fleet-Crew! 👋
Cassian hier – heute schieben wir eine Desktop-App über die Linie: Swing → Native Image.
Ziel: schneller Start, einfache Verteilung, keine JVM-Installation beim Endnutzer.
Projekt anlegen
1) Minimaler Code (Swing)
package com.example.swingnative;
import javax.swing.*;
import java.awt.*;
import java.net.URL;
public class Main {
public static void main(String[] args) {
System.setProperty("java.awt.headless", "false");
SwingUtilities.invokeLater(() -> {
JFrame f = new JFrame("Swing Native Image");
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.setSize(480, 320);
f.setLocationRelativeTo(null);
URL iconUrl = Main.class.getResource("/icons/app.png");
if (iconUrl != null) {
ImageIcon icon = new ImageIcon(iconUrl);
f.setIconImage(icon.getImage());
}
f.add(new JLabel("Hello, Native Image! 🚀", SwingConstants.CENTER), BorderLayout.CENTER);
JMenuBar bar = new JMenuBar();
JMenu file = new JMenu("Datei");
file.add(new JMenuItem("Beenden"));
bar.add(file);
f.setJMenuBar(bar);
f.setVisible(true);
});
}
}
Maven einrichten
2) Basis-POM
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>swing-native</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.release>21</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<graalvm.native.plugin.version>0.11.0</graalvm.native.plugin.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<archive>
<manifest>
<mainClass>com.example.swingnative.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<version>${graalvm.native.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<imageName>swing-native</imageName>
<mainClass>com.example.swingnative.Main</mainClass>
<fallback>false</fallback>
<verbose>true</verbose>
<buildArgs>
<buildArg>--no-fallback</buildArg>
<buildArg>--initialize-at-build-time</buildArg>
<buildArg>--enable-https</buildArg>
</buildArgs>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>native</id>
<properties>
<skipTests>true</skipTests>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<version>${graalvm.native.plugin.version}</version>
<executions>
<execution>
<id>build-native</id>
<goals>
<goal>compile-no-fork</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
Ressourcen & Reflection korrekt einbinden
3) Ressourcen (Icons, Properties)
{
"resources": {
"includes": [
{ "pattern": "icons/.*\.png$" },
{ "pattern": ".*\.properties$" }
]
}
}
4) Reflection / Dynamik (falls gebraucht)
mvn -Pnative -Dagent=true test mvn -Pnative -Dagent=true -DskipTests -DskipNativeBuild=true package exec:exec@java-agent
OS-Voraussetzungen & Build
5) GraalVM JDK & Tools
- macOS: Xcode CLT
- Linux: build-essential / gcc
- Windows: MS Visual Studio Build Tools
6) Build-Befehle
macOS/Linux:
mvn -Pnative -DskipTests package ./target/swing-native
Windows:
mvn -Pnative -DskipTests package target\swing-native.exe
🚀 Ergebnis
Ein klickbares Binary pro OS, ohne JVM. Start spürbar schneller, Distribution einfacher.
🗓️ Nächste Woche: Packaging & Distribution mit jpackage
„macOS .app, Windows .msi, Linux .deb/.rpm – mit jpackage & Codesigning“
❓ FAQ – Swing Native Image Edition
Q: Brauche ich immer resource-config.json?
A: Nur für Klassenpfad-Ressourcen.
Q: Wie gehe ich mit Reflection um?
A: Agent laufen lassen, Konfigs übernehmen.
Q: Kann ich ohne das Maven-Plugin bauen?
A: Ja, via CLI und dem Befehl native-image.
Q: Wie aktiviere ich HTTPS?
A: Über –enable-https.
Q: Windows-Tipp?
A: Immer „x64 Native Tools Command Prompt“ nutzen.
📖 GraalVM – Alle Teile im Überblick
- Teil 1: Der heilige Graal
- Teil 2: Native Images – Wo Java schnell wird
- Teil 3: Enterprise Production
- Teil 4: Swing Native Image
- Teil 5: Packaging mit jpackage
Tags: #GraalVM #NativeImage #Swing #Java #Maven #macOS #Linux #Windows

