A demo of sqlite4j — SQLite compiled to pure JVM bytecode via Chicory (no JNI) — used from Clojure with next.jdbc, including GraalVM native-image compilation.
- Clojure CLI 1.12+
- GraalVM with
native-image(for native compilation)
clojure -M -m sqlite4j-demo.mainBuild the uberjar:
clojure -T:build uberCompile to native:
native-image -jar target/sqlite4j-demo.jar \
-o sqlite4j-demo \
-H:ReflectionConfigurationFiles=reflect-config.json \
-H:+ReportExceptionStackTraces \
--features=clj_easy.graal_build_time.InitClojureClasses \
--initialize-at-build-time=io.roastedroot.zerofs \
--initialize-at-build-time=io.roastedroot.sqlite4j \
--initialize-at-build-time=com.dylibso.chicory \
--initialize-at-run-time=io.roastedroot.sqlite4j.JDBC \
--no-fallbackRun the binary:
./sqlite4j-demoThe key insight for native-image is the initialization timing:
io.roastedroot.sqlite4j,io.roastedroot.zerofs, andcom.dylibso.chicoryare initialized at build timeio.roastedroot.sqlite4j.JDBCmust be initialized at run time so it registers withjava.sql.DriverManagerwhen the binary starts