Backend Development 8 min read

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.

Java Architecture Diary
Java Architecture Diary
Java Architecture Diary
Compile mica-mqtt into a Lightning‑Fast Native Executable with GraalVM

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>&lt;dependency&gt;
  &lt;groupId&gt;org.graalvm.sdk&lt;/groupId&gt;
  &lt;artifactId&gt;graal-sdk&lt;/artifactId&gt;
  &lt;version&gt;${graalvm.version}&lt;/version&gt;
  &lt;scope&gt;provided&lt;/scope&gt;
&lt;/dependency&gt;</code>

3.3 Add Maven Plugin

<code>&lt;plugin&gt;
  &lt;groupId&gt;org.graalvm.nativeimage&lt;/groupId&gt;
  &lt;artifactId&gt;native-image-maven-plugin&lt;/artifactId&gt;
  &lt;version&gt;${graalvm.version}&lt;/version&gt;
  &lt;executions&gt;
    &lt;execution&gt;
      &lt;goals&gt;
        &lt;goal&gt;native-image&lt;/goal&gt;
      &lt;/goals&gt;
      &lt;phase&gt;package&lt;/phase&gt;
    &lt;/execution&gt;
  &lt;/executions&gt;
  &lt;configuration&gt;
    &lt;skip&gt;false&lt;/skip&gt;
    &lt;imageName&gt;mqtt-server-graalvm&lt;/imageName&gt;
    &lt;mainClass&gt;${mainClass.server}&lt;/mainClass&gt;
    &lt;buildArgs&gt;
      --enable-all-security-services
      --report-unsupported-elements-at-runtime
      -H:+RemoveSaturatedTypeFlows
      --allow-incomplete-classpath
      -H:ReflectionConfigurationFiles=../graalvm/reflect-config.json
    &lt;/buildArgs&gt;
  &lt;/configuration&gt;
&lt;/plugin&gt;</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>&lt;dependency&gt;
  &lt;groupId&gt;com.github.ben-manes.caffeine&lt;/groupId&gt;
  &lt;artifactId&gt;caffeine&lt;/artifactId&gt;
  &lt;version&gt;3.0.3&lt;/version&gt;
&lt;/dependency&gt;</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>&lt;dependency&gt;
  &lt;groupId&gt;org.slf4j&lt;/groupId&gt;
  &lt;artifactId&gt;slf4j-jdk14&lt;/artifactId&gt;
  &lt;version&gt;1.7.31&lt;/version&gt;
&lt;/dependency&gt;</code>

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.

JavaperformancecaffeineGraalVMnative-imageMQTTt-io
Java Architecture Diary
Written by

Java Architecture Diary

Committed to sharing original, high‑quality technical articles; no fluff or promotional content.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.