⌘K ctrl+k
Search Shortcut cmd + k | ctrl + k
Deploy as Native Image

Overview

The JDBC driver runs inside GraalVM Native Image executables. Graal Native Image compiles a Java application ahead of time into a standalone binary that starts in milliseconds and requires no JVM on the target machine, which suits command line tools, serverless functions, and small containers.

Recent driver versions ship the JNI reachability metadata that native-image needs, and the build picks it up automatically from the class path.

Two things remain for the application to configure: native access and the location of DuckDB's shared library.

Driver versions up to and including 1.5.5 do not ship this metadata. For those versions, generate it by running the application once on the JVM with the tracing agent:

java -agentlib:native-image-agent=config-output-dir=⟨config_dir⟩ -cp ⟨classpath⟩ ⟨MainClass⟩

Next, pass the directory to the build with -H:ConfigurationFileDirectories=⟨config_dir⟩.

Requirements

GraalVM for JDK 22 or later is required. Older GraalVM releases initialize the driver's classes at image build time, which bakes a build machine path into the executable and fails at run time with UnsatisfiedLinkError.

Pass --enable-native-access=ALL-UNNAMED to native-image, or add it as a build argument in the Native Build Tools Maven or Gradle plugin.

Load the driver explicitly before opening the first connection:

Class.forName("org.duckdb.DuckDBDriver");

Driver auto-registration through ServiceLoader is not always visible to Graal Native Image's closed world analysis, and the explicit load makes registration deterministic.

Providing the Shared Library

DuckDB's engine is a native library bundled inside the driver JAR, one file per platform. Choose one of two ways to make it available to the executable.

Option 1: Embed the Library in the Executable

Add a resource entry naming your platform's library, either in a configuration directory passed via -H:ConfigurationFileDirectories or under META-INF/native-image in your own project:

{ "resources": { "includes": [ { "pattern": "libduckdb_java\\.so_linux_amd64" } ] } }

The bundled library names are libduckdb_java.so_linux_amd64, libduckdb_java.so_linux_arm64, libduckdb_java.so_osx_universal, and libduckdb_java.so_windows_amd64.

Name the one for your target platform explicitly. A wildcard matching all of them adds roughly 260 MB to the executable.

This option produces a single self contained file, around 120 MB. The driver extracts the library to a temporary directory when the first connection opens, which adds up to a second of startup time and requires a writable temporary directory.

Option 2: Ship the Library Next to the Executable

Build without any resource entry and place the shared library in the same directory as the executable. The file works under its bundled name, for example libduckdb_java.so_linux_amd64, or under the platform convention: libduckdb_java.so on Linux, libduckdb_java.dylib on macOS, duckdb_java.dll on Windows. The lookup is anchored to the executable rather than the working directory, so the program runs correctly from anywhere.

This option produces a small executable, under 20 MB for a simple application, with no extraction cost when connections open. The library can be extracted from the driver JAR, or taken from the -nolib distribution together with its separate library artifact.

Building

A minimal build, with the driver JAR in the current directory:

javac -cp duckdb_jdbc-⟨version⟩.jar App.java
native-image --no-fallback --enable-native-access=ALL-UNNAMED \
    -cp duckdb_jdbc-⟨version⟩.jar:. -o app App

--no-fallback makes the build fail outright instead of producing an image that still requires a JVM. For Maven and Gradle projects, the Native Build Tools plugins wrap the same build and run it during mvn package or gradle nativeCompile.

Further Reading

  • Troubleshoot — the Native Image errors that indicate missing metadata or a missing shared library.
  • Define Connections — driver registration and connection configuration.
  • Java (JDBC) Client — installing the driver from Maven Central.
© 2026 DuckDB Foundation, Amsterdam NL
DuckDB Home Code of Conduct Trademark Use Blog