Compile mica-mqtt into a Lightning‑Fast Native Executable with GraalVM
This guide walks through building the mica-mqtt MQTT component with GraalVM native-image, covering dependency setup, Caffeine configuration, Maven plugin settings, binary compression with UPX, and performance comparisons that demonstrate millisecond‑level startup versus traditional JAR execution.
1. Introduction
Hello everyone, I am Spring brother (mica), and we have been following and exploring the use of GraalVM and Spring Native.
We have translated several articles, including a GraalVM quick reference, a Spring Native hands‑on tutorial, a discussion on whether Spring Native is production‑ready, and a guide on high‑performance Java with GraalVM.
2. mica-mqtt
t‑io is a high‑performance, low‑latency network framework that is easy to use and provides many practical features not found in other frameworks. More information can be found at https://www.tiocloud.com.
mica‑mqtt is an MQTT IoT component I developed based on t‑io, containing both client and server implementations and supporting MQTT v3.1, v3.1.1, and v5.0. In recent benchmark tests against other popular MQTT libraries (including Netty and Reactor‑Netty), mica‑mqtt showed significantly faster connection speeds. The source code is available at https://gitee.com/596392912/mica-mqtt.
3. Supporting GraalVM
Because t‑io has few dependencies—only fastjson and caffeine—compiling it to a native executable is relatively straightforward.
3.1 Install GraalVM – see our previous article for details.
Note: caffeine 3.x requires at least Java 11, so use the graalvm‑ce‑java11 distribution.
3.2 Add Dependency
<code><dependency>
<groupId>org.graalvm.sdk</groupId>
<artifactId>graal-sdk</artifactId>
<version>${graalvm.version}</version>
<scope>provided</scope>
</dependency></code>3.3 Add Maven Plugin
<code><plugin>
<groupId>org.graalvm.nativeimage</groupId>
<artifactId>native-image-maven-plugin</artifactId>
<version>${graalvm.version}</version>
<executions>
<execution>
<goals>
<goal>native-image</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
<configuration>
<skip>false</skip>
<imageName>mqtt-server-graalvm</imageName>
<mainClass>${mainClass.server}</mainClass>
<buildArgs>
--enable-all-security-services
--report-unsupported-elements-at-runtime
-H:+RemoveSaturatedTypeFlows
--allow-incomplete-classpath
-H:ReflectionConfigurationFiles=../graalvm/reflect-config.json
</buildArgs>
</configuration>
</plugin></code>3.4 Caffeine handling – replace the built‑in caffeine 2.x with caffeine 3.x to reduce reflection and Unsafe usage, which improves GraalVM compatibility.
<code><dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>3.0.3</version>
</dependency></code>The required reflection configuration (reflect‑config.json) is:
<code>[
{"name":"com.github.benmanes.caffeine.cache.PSW","allDeclaredConstructors":true},
{"name":"com.github.benmanes.caffeine.cache.PSWMS","allDeclaredConstructors":true},
{"name":"com.github.benmanes.caffeine.cache.SSLA","allDeclaredConstructors":true},
{"name":"com.github.benmanes.caffeine.cache.SSLMSW","allDeclaredConstructors":true},
{"name":"com.github.benmanes.caffeine.cache.SSMSW","allDeclaredConstructors":true},
{"name":"com.github.benmanes.caffeine.cache.SSLMSA","allDeclaredConstructors":true},
{"name":"com.github.benmanes.caffeine.cache.PSAMS","allDeclaredConstructors":true}
]</code>3.5 Logging – to keep the configuration minimal, use the JDK logger:
<code><dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.7.31</version>
</dependency></code>4. Build
mica‑mqtt defines two Maven profiles:
mqtt-client-graaland
mqtt-server-graal.
After the package phase, the
targetdirectory contains two executable files:
mqtt-server-graalvmand
mqtt-client-graalvm. On Windows the files have the
.exeextension.
5. Compression and Performance
Using
upxto compress the executables reduces their size from 30‑40 MB to around 10 MB.
Running
./mqtt-server-graalvmstarts in milliseconds, as shown by the startup log.
For comparison, the same application packaged as a regular JAR shows a much slower startup:
6. Demo
Note: An exception log from caffeine may appear; it is caused by a reflection check and can be safely ignored.
Java Architecture Diary
Committed to sharing original, high‑quality technical articles; no fluff or promotional content.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.