How to Build a Minimal GraalVM Native Image for a Solon Java App
This guide walks through setting up GraalVM on Ubuntu, configuring environment variables, handling native-image agent pitfalls, fixing H2 database class‑loading issues, and finally producing a compact native executable for a Solon‑based Java service with memory‑optimisation tips.
Environment
System: Ubuntu 16.04
GraalVM: GraalVM Community 21.3.0 (based on OpenJDK 11.0.13)
Preparation
Set JAVA_HOME to the GraalVM directory
Add $JAVA_HOME/bin to
PATH export JAVA_HOME=/path/to/graalvm
export PATH=$JAVA_HOME/bin:$PATHInstall the native‑image tool: gu install native-image Install required build packages:
apt-get install build-essential libz-dev zlib1g-devNote: The linker ld must be version 2.26+; otherwise the build will fail.
Packaging
First build the project JAR with Maven (e.g., solondemo.jar) and verify it runs: java -jar solondemo.jar Collect configuration data with the native‑image agent (skip if the project does not use reflection or proxies):
java -agentlib:native-image-agent=config-output-dir=./config/ -jar solondemo.jarRun tests to achieve near‑100% coverage, then merge the generated config files if needed:
java -agentlib:native-image-agent=config-merge-dir=./config/ -jar solondemo.jarThe agent produces five JSON files ( jni-config.json, predefined-classes-config.json, proxy-config.json, reflect-config.json, resource-config.json, serialization-config.json) that must be packaged into META-INF/native-image or supplied via -H:ConfigurationFileDirectories=./config. On Ubuntu the latter works; on CentOS it may be mis‑interpreted.
Because GraalVM treats resources differently, scanning directories like META-INF/solon fails. The workaround is to pre‑list required files and make the resource scanner treat them as regular files.
Fixing H2 Database Issues
The native image initially fails with ClassNotFoundException for H2 file‑system classes. Adding the missing classes to reflect-config.json resolves the problem. Example entry:
{"name":"org.h2.store.fs.FilePathDisk","methods":[{"name":"<init>","parameterTypes":[]} ]}Repeat until all required classes are covered.
Final Native‑Image Command
native-image -jar solondemo.jar \
--allow-incomplete-classpath \
-H:+ReportExceptionStackTraces \
--enable-httpUse --enable-https if HTTPS is required. The resulting binary runs correctly, serving HTTP endpoints, static pages, and logging.
Additional Tips
The native‑image agent may miss some reflective calls; manually add them to reflect-config.json.
GraalVM’s custom file system cannot traverse directories; pre‑configure file lists.
Third‑party libraries often fail due to missing reflection metadata.
Native‑image builds need >5 GB RAM; set memory limits with -Xmx and -XX:MaxDirectMemorySize when running the binary.
References
GraalVM download: https://www.graalvm.org/downloads/
Native‑image quick reference PDF (linked in the original article).
Solon framework source: https://gitee.com/noear/solon
Demo project: https://gitee.com/mantouchong/solondemo
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.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
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.
