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
<dependency>
<groupId>org.graalvm.sdk</groupId>
<artifactId>graal-sdk</artifactId>
<version>${graalvm.version}</version>
<scope>provided</scope>
</dependency>3.3 Add Maven Plugin
<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>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.
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>3.0.3</version>
</dependency>The required reflection configuration (reflect‑config.json) is:
[
{"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}
]3.5 Logging – to keep the configuration minimal, use the JDK logger:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.7.31</version>
</dependency>4. Build
mica‑mqtt defines two Maven profiles: mqtt-client-graal and mqtt-server-graal.
After the package phase, the target directory contains two executable files: mqtt-server-graalvm and mqtt-client-graalvm. On Windows the files have the .exe extension.
5. Compression and Performance
Using upx to compress the executables reduces their size from 30‑40 MB to around 10 MB.
Running ./mqtt-server-graalvm starts 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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
