
Graal
- 210 installs
- 779 repo stars
- Updated August 4, 2026
- oracle/skills
Configure GraalVM polyglot runtimes and native images for fast JVM services, CLI tools, and multi-language backends with tuned startup and memory profiles.
About
Oracle GraalVM guidance from oracle/skills for polyglot JVM applications, native image compilation, performance tuning, and runtime configuration when building fast Java and multi-language backend or CLI services.
- Native image compilation
- Polyglot runtime setup
- Startup optimization
- Memory tuning guidance
- JVM service packaging
Graal by the numbers
- 210 all-time installs (skills.sh)
- +13 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #23 of 89 Java & JVM skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/oracle/skills --skill graalAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 210 |
|---|---|
| repo stars | ★ 779 |
| Last updated | August 4, 2026 |
| Repository | oracle/skills ↗ |
What it does
Configure GraalVM polyglot runtimes and native images for fast JVM services, CLI tools, and multi-language backends with tuned startup and memory profiles.
Files
Oracle Graal Skills
Use this domain to build, configure, and troubleshoot GraalVM Native Image applications with Maven, Gradle, or the CLI.
How to Use This Domain
1. Start with the routing table below. 2. Read only the specific Native Image file needed for the task. 3. Prefer Native Build Tools for Maven or Gradle projects. Use the raw native-image workflow for simple Java files or direct CLI usage.
Directory Structure
graal/
|-- SKILL.md
`-- native-image/
|-- build-native-image.md
|-- native-build-tools.md
|-- reachability-metadata.md
`-- troubleshooting.mdCategory Routing
| Topic | File |
|---|---|
native-image CLI builds, options, classpath, modules, output names, binary type, optimization, URL protocols, monitoring, security | graal/native-image/build-native-image.md |
Maven native-maven-plugin, Gradle org.graalvm.buildtools.native, build-tool tasks, plugin options, and native test routing | graal/native-image/native-build-tools.md |
Missing reflection, JNI, resources, resource bundles, serialization, dynamic proxies, conditional metadata, and reachability-metadata.json layout | graal/native-image/reachability-metadata.md |
| Build failures, runtime failures, missing metadata symptoms, class initialization issues, memory issues, diagnostics, Maven activation issues, and where to route fixes | graal/native-image/troubleshooting.md |
Key Starting Points
graal/native-image/build-native-image.mdgraal/native-image/native-build-tools.mdgraal/native-image/reachability-metadata.mdgraal/native-image/troubleshooting.md
Common Multi-Step Flows
| Task | Recommended Sequence |
|---|---|
| Build a Java class with Native Image | native-image/build-native-image.md |
| Configure a Maven or Gradle project for Native Image | native-image/native-build-tools.md -> native-image/build-native-image.md for flags |
| Fix missing reflection, JNI, proxy, resource, bundle, or serialization metadata | native-image/reachability-metadata.md |
| Diagnose build failures or runtime behavior differences | native-image/troubleshooting.md -> native-image/build-native-image.md -> native-image/reachability-metadata.md if metadata is involved |
Sources
- https://github.com/oracle/graal/tree/master/substratevm/skills/building-native-image
- https://github.com/oracle/graal/tree/master/substratevm/skills/build-native-image-maven
- https://github.com/oracle/graal/tree/master/substratevm/skills/build-native-image-gradle
- https://www.graalvm.org/latest/reference-manual/native-image/
Building Native Image
Overview
Use this skill to build Java applications with GraalVM Native Image and configure raw native-image command-line options.
Prerequisites
- Set
JAVA_HOMEto a GraalVM distribution if your Java program uses the Native Image SDK. If you do not know the path, ask the user to provide it.
Build and Run
Use native-build-tools.md whenever possible for Maven or Gradle projects. Use the raw native-image command directly for simple Java files or cases where the user specifically asks for direct CLI usage.
1. Compile your Java file with javac. 2. Build the Native Image:
$JAVA_HOME/bin/native-image <app-name>3. Run the resulting executable:
./app-name4. For classpath-based builds, pass the classpath explicitly with the -cp option.
Classpath and Modules
For classpath-based applications:
native-image -cp <path1>:<path2> <class>If using modules:
native-image -p <module-path> --add-modules <module-name> <class>Build-Time Inputs
If you need to set a system property at build time:
native-image -Dkey=value <class>If you need to pass a flag to the JVM running the builder:
native-image -J<flag> <class>For class initialization, linking, builder memory, or missing metadata failures, use troubleshooting.md. For metadata file structure and JSON entries, see reachability-metadata.md.
Output and Binary Type
If you want to rename the output binary:
native-image -o myapp <class>If you want to build a shared library:
native-image --shared <class>If you want a fully statically linked binary:
native-image --static --libc=musl <class>If you want static linking but keep libc dynamic:
native-image --static-nolibc <class>Performance and Optimization
If you want fastest build time during development iteration:
native-image -Ob <class>If you want best runtime performance:
native-image -O3 <class>If you want to optimize for binary size:
native-image -Os <class>If you want to change the garbage collector:
native-image --gc=epsilon <class> # no GC (throughput)
native-image --gc=serial <class> # defaultIf you want to target the current machine's CPU features:
native-image -march=native <class>If you need maximum compatibility across machines:
native-image -march=compatibility <class>If you want to limit build parallelism:
native-image --parallelism=4 <class>Network Support
If the binary needs HTTP/HTTPS:
native-image --enable-http --enable-https <class>If the binary needs specific URL protocols:
native-image --enable-url-protocols=http,https <class>Monitoring and Observability
If you need runtime monitoring such as heap dumps, JFR, or thread dumps:
native-image --enable-monitoring=heapdump,jfr,threaddump <class>Security and Compliance
If you need all security services, such as TLS/SSL:
native-image --enable-all-security-services <class>Cross-Compilation and Platform
If you need to cross-compile for a different OS or architecture:
native-image --target=linux-aarch64 <class>If you need a custom C compiler:
native-image --native-compiler-path=/usr/bin/gcc <class>Info and Discovery
If you want to list available CPU features:
native-image --list-cpu-featuresIf you want to list observable modules:
native-image --list-modulesIf you want to see the native toolchain and build settings:
native-image --native-image-infoTroubleshooting
If you encounter runtime errors related to reflection, JNI, resources, serialization, or dynamic proxies, see reachability-metadata.md before attempting a fix. For problem-based routing, see troubleshooting.md.
Sources
- https://github.com/oracle/graal/tree/master/substratevm/skills/building-native-image
- https://www.graalvm.org/latest/reference-manual/native-image/
- https://www.graalvm.org/latest/reference-manual/native-image/overview/Options/
GraalVM Native Build Tools
Overview
Use this skill to build GraalVM native images with Maven or Gradle. Use build-native-image.md for raw native-image flags and reachability-metadata.md for manual metadata JSON.
Maven Native Image Build
Prerequisites
- Set
JAVA_HOMEto a GraalVM JDK installation so the plugin can findnative-image. - Do not require
GRAALVM_HOMEin the normal case. Only mention it if the user already relies on it or their environment needs an explicit override. - Use Maven 3.6+.
Plugin Setup
Add the following to pom.xml:
<profiles>
<profile>
<id>native</id>
<build>
<plugins>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<version>0.11.1</version>
<extensions>true</extensions>
<executions>
<execution>
<id>build-native</id>
<goals>
<goal>compile-no-fork</goal>
</goals>
<phase>package</phase>
</execution>
<execution>
<id>test-native</id>
<goals>
<goal>test</goal>
</goals>
<phase>test</phase>
</execution>
</executions>
<configuration>
<mainClass>org.example.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>Build and Run
./mvnw -Pnative package # Build native image to target/<imageName>
./target/myapp # Run the native executable
./mvnw -Pnative test # Build and run JUnit tests as a native image
./mvnw -Pnative -DskipTests package # Skip all tests
./mvnw -Pnative -DskipNativeTests package # Run JVM tests only, skip nativeMaven Configuration Options
| Option | Type | Default | Purpose |
|---|---|---|---|
<imageName> | String | artifactId | Name of the output executable |
<mainClass> | String | none | Entry point class (required) |
<debug> | boolean | false | Generate debug info |
<verbose> | boolean | false | Enable verbose build output |
<fallback> | boolean | false | Allow fallback to JVM |
<sharedLibrary> | boolean | false | Build shared library instead of executable |
<quickBuild> | boolean | false | Faster build, lower runtime performance |
<useArgFile> | boolean | true | Use argument file for long classpaths |
<skipNativeBuild> | boolean | false | Skip native compilation |
<skipNativeTests> | boolean | false | Skip native test execution |
<buildArgs> | List | empty | Arguments passed directly to native-image |
<jvmArgs> | List | empty | JVM arguments for the native-image builder |
<runtimeArgs> | List | empty | Arguments passed to the app at runtime |
<environment> | Map | empty | Environment variables during build |
<systemPropertyVariables> | Map | empty | System properties during build |
<classpath> | List | auto | Override classpath entries |
<classesDirectory> | String | auto | Override classes directory |
Pass any native-image flag via <buildArgs>:
<buildArgs>
<buildArg>--initialize-at-run-time=com.example.LazyClass</buildArg>
<buildArg>-H:IncludeResources=.*\.xml$</buildArg>
<buildArg>-O2</buildArg>
</buildArgs>If the build runs out of memory:
<jvmArgs>
<arg>-Xmx8g</arg>
</jvmArgs>Child projects can append build arguments to a parent POM config using combine.children:
<buildArgs combine.children="append">
<buildArg>--verbose</buildArg>
</buildArgs>If using maven-shade-plugin, point the native plugin to the shaded JAR:
<configuration>
<useArgFile>false</useArgFile>
<classpath>
<param>${project.build.directory}/${project.artifactId}-${project.version}-shaded.jar</param>
</classpath>
</configuration>Maven Plugin Not Resolving or Activating
"Could not resolve artifact"- EnsuremavenCentral()is in repositories and the version is correct."Could not find goal 'compile-no-fork'"- Verify<extensions>true</extensions>is set on the plugin.- Build runs without native compilation - Check you are activating the profile:
./mvnw -Pnative package.
Gradle Native Image Build
Prerequisites
- Set
JAVA_HOMEto a GraalVM JDK installation so Gradle Native Build Tools can findnative-image. - Do not require
GRAALVM_HOMEin the normal case. Only mention it if the user already relies on it or their environment needs an explicit override. - Apply the
application,java-library, orjavaplugin along withorg.graalvm.buildtools.native.
Plugin Setup
Groovy DSL:
plugins {
id 'application'
id 'org.graalvm.buildtools.native' version '0.11.1'
}Kotlin DSL:
plugins {
application
id("org.graalvm.buildtools.native") version "0.11.1"
}Build and Run
./gradlew nativeCompile # Build to build/native/nativeCompile/
./gradlew nativeRun # Build and run the native executable
./gradlew nativeTest # Build and run JUnit tests as a native imageGradle DSL Structure
graalvmNative {
binaries {
main { /* application binary options */ }
test { /* test binary options */ }
all { /* shared options */ }
}
}Gradle Binary Properties
| Property | Type | Default | Description |
|---|---|---|---|
imageName | String | project name | Output executable name |
mainClass | String | application.mainClass | Main entry point class |
debug | boolean | false | Enable debug info, or use --debug-native |
verbose | boolean | false | Verbose build output |
sharedLibrary | boolean | false | Build a shared library |
quickBuild | boolean | false | Faster build, lower runtime performance |
richOutput | boolean | false | Rich console output |
jvmArgs | ListProperty | empty | JVM arguments for native-image builder |
buildArgs | ListProperty | empty | Arguments for native-image |
runtimeArgs | ListProperty | empty | Arguments for the application at runtime |
javaLauncher | Property | auto-detected | GraalVM toolchain launcher |
Gradle Binary Configuration
Rename the output binary:
imageName = 'myapp'Set the entry point:
mainClass = 'com.example.Main'Enable debug info:
debug = true
// or use --debug-nativeVerbose build output:
verbose = trueFaster builds during development:
quickBuild = true
// or use -Ob buildArg for maximum speed
buildArgs.add('-Ob')Build a shared library instead of an executable:
sharedLibrary = trueIncrease build memory:
jvmArgs.add('-Xmx8g')Force runtime initialization for a class:
buildArgs.add('--initialize-at-run-time=com.example.LazyClass')Force build-time initialization for a class:
buildArgs.add('--initialize-at-build-time=com.example.EagerClass')Inspect build diagnostics:
buildArgs.add('--diagnostics-mode')Include resource files at runtime:
buildArgs.add('-H:IncludeResources=.*\\.(properties|xml)$')Pass arguments to the application at startup:
runtimeArgs.add('--server.port=8080')Gradle Full Example
Groovy DSL:
graalvmNative {
binaries {
main {
imageName = 'myapp'
mainClass = 'com.example.Main'
verbose = true
buildArgs.addAll(
'--initialize-at-run-time=com.example.Lazy',
'-H:IncludeResources=.*\\.properties$',
'-O3'
)
jvmArgs.add('-Xmx8g')
}
test {
imageName = 'myapp-tests'
}
all {
javaLauncher = javaToolchains.launcherFor {
languageVersion.set(JavaLanguageVersion.of(21))
}
}
}
}Kotlin DSL:
graalvmNative {
binaries {
named("main") {
imageName.set("myapp")
mainClass.set("com.example.Main")
verbose.set(true)
buildArgs.addAll(
"--initialize-at-run-time=com.example.Lazy",
"-H:IncludeResources=.*\\.properties$",
"-O3"
)
jvmArgs.add("-Xmx8g")
}
named("test") {
imageName.set("myapp-tests")
}
}
}Missing Reachability Metadata
When Native Image reports missing reflection, resources, serialization, proxy, or JNI entries, use reachability-metadata.md.
To enable exact metadata checking and warning mode in Maven, add to plugin configuration:
<configuration>
<buildArgs>
<buildArg>--exact-reachability-metadata</buildArg>
</buildArgs>
<runtimeArgs>
<runtimeArg>-XX:MissingRegistrationReportingMode=Warn</runtimeArg>
</runtimeArgs>
</configuration>To enable exact metadata checking and warning mode in Gradle, add to binaries.all:
graalvmNative {
binaries.all {
buildArgs.add('--exact-reachability-metadata')
runtimeArgs.add('-XX:MissingRegistrationReportingMode=Warn')
}
}To collect metadata with the Gradle tracing agent:
./gradlew generateMetadata -Pcoordinates=<library-coordinates> -PagentAllowedPackages=<condition-packages>Native Testing
For Maven native tests:
./mvnw -Pnative testFor Gradle native tests:
./gradlew nativeTestThe Gradle native test binary is located at:
build/native/nativeTestCompile/<imageName>Sources
- https://github.com/oracle/graal/tree/master/substratevm/skills/build-native-image-maven
- https://github.com/oracle/graal/tree/master/substratevm/skills/build-native-image-gradle
- https://graalvm.github.io/native-build-tools/latest/index.html
GraalVM Native Image Reachability Metadata
Table of Contents
1. Diagnosing the Error Type 2. Where to Put Metadata Files 3. Reflection Metadata 4. JNI Metadata 5. Resource Metadata 6. Serialization Metadata 7. Conditional Metadata Entries 8. Full Sample reachability-metadata.json
1. Diagnosing the Error Type
Match the runtime error to the metadata section you need to fix:
| Runtime Error | Root Cause | Fix In Section |
|---|---|---|
NoClassDefFoundError | Class not included in binary | Reflection Metadata - register the type |
MissingReflectionRegistrationError | Reflective access to unregistered class/method/field | Reflection Metadata |
NoSuchMethodException | Method not registered for reflective invocation | Reflection Metadata - Methods |
NoSuchFieldException | Field not registered for reflective access | Reflection Metadata - Fields |
MissingJNIRegistrationError | JNI lookup of unregistered type/member | JNI Metadata |
MissingForeignRegistrationError | FFM downcall/upcall without registered descriptor | Foreign section (advanced, see GraalVM docs) |
MissingResourceException | Resource bundle not included | Resource Metadata - Bundles |
Quick diagnostic command - run the app with warning mode to see all missing registrations without crashing:
java -XX:MissingRegistrationReportingMode=Warn -jar your-app.jarUse Exit mode during testing to catch errors hidden inside catch (Throwable t) blocks:
java -XX:MissingRegistrationReportingMode=Exit -jar your-app.jarEnable strict metadata mode at build time:
native-image --exact-reachability-metadata ...
# Or for specific packages only:
native-image --exact-reachability-metadata=com.example.mypackage ...---
2. Where to Put Metadata Files
All metadata lives in a single JSON file on the classpath:
src/main/resources/
└── META-INF/
└── native-image/
└── <groupId>/
└── <artifactId>/
└── reachability-metadata.jsonThe file contains a top-level object with one key per metadata type:
{
"reflection": [],
"resources": []
}Alternative approaches (when JSON isn't enough):
- Pass constant arguments toClass.forName("Foo"),getMethod(...), etc. - native-image evaluates these at build time automatically.
- Use -H:Preserve=<package> to preserve entire packages.---
3. Reflection Metadata
Register a Type (fixes NoClassDefFoundError, MissingReflectionRegistrationError)
{
"reflection": [
{
"type": "com.example.MyClass"
}
]
}This allows Class.forName("com.example.MyClass") and reflective lookups to find the type.
Methods
Fixes NoSuchMethodError and MissingReflectionRegistrationError on Method.invoke() or Constructor.newInstance().
Register specific methods:
{
"type": "com.example.MyClass",
"methods": [
{ "name": "myMethod", "parameterTypes": ["java.lang.String", "int"] },
{ "name": "<init>", "parameterTypes": [] }
]
}Use "<init>" for constructors.Register all methods (less precise, larger binary):
{
"type": "com.example.MyClass",
"allDeclaredMethods": true,
"allPublicMethods": true,
"allDeclaredConstructors": true,
"allPublicConstructors": true
}allDeclared*- methods/constructors declared directly on this typeallPublic*- all public methods/constructors including those inherited from supertypes
Fields
Fixes NoSuchFieldException and MissingReflectionRegistrationError on Field.get() / Field.set().
Register specific fields:
{
"type": "com.example.MyClass",
"fields": [
{ "name": "myField" },
{ "name": "anotherField" }
]
}Register all fields:
{
"type": "com.example.MyClass",
"allDeclaredFields": true,
"allPublicFields": true
}Dynamic Proxies
For classes obtained via Proxy.newProxyInstance(...) - the type is the proxy's interface list:
{
"type": {
"proxy": ["com.example.IFoo", "com.example.IBar"]
}
}The interface order matters - it must match the order passed to Proxy.newProxyInstance.Unsafe Allocation
For Unsafe.allocateInstance(MyClass.class):
{
"type": "com.example.MyClass",
"unsafeAllocated": true
}Full Type Entry Reference
{
"condition": { "typeReached": "com.example.TriggerClass" },
"type": "com.example.MyClass",
"fields": [{ "name": "fieldName" }],
"methods": [{ "name": "methodName", "parameterTypes": ["java.lang.String"] }],
"allDeclaredConstructors": true,
"allPublicConstructors": true,
"allDeclaredMethods": true,
"allPublicMethods": true,
"allDeclaredFields": true,
"allPublicFields": true,
"unsafeAllocated": true,
"serializable": true
}---
4. JNI Metadata
Used when native C/C++ code calls back into Java via JNI. Fixes MissingJNIRegistrationError.
Most JNI libraries don't handle Java exceptions gracefully - always use--exact-reachability-metadatawith-XX:MissingRegistrationReportingMode=Warnto see what's missing.
Register a JNI-accessible type:
{
"reflection": [
{
"type": "com.example.MyClass",
"jniAccessible": true
}
]
}Add fields and methods for JNI access:
{
"type": "com.example.MyClass",
"jniAccessible": true,
"fields": [{ "name": "value" }],
"methods": [
{ "name": "callback", "parameterTypes": ["int"] }
],
"allDeclaredConstructors": true
}JNI metadata follows the same allDeclared* / allPublic* convenience flags as reflection.
---
5. Resource Metadata
Embed Resources (fixes missing getResourceAsStream results)
Resources are specified using glob patterns in the resources array:
{
"resources": [
{ "glob": "config/app.properties" },
{ "glob": "templates/**" },
{ "glob": "**/Resource*.txt" }
]
}Glob rules:
*matches any characters on one path level**matches any characters across multiple levels- No trailing slash, no empty levels, no
***
Examples:
{ "glob": "config/app.properties" } // exact file
{ "glob": "**/**.json" } // all JSON files anywhere
{ "glob": "static/images/*.png" } // all PNGs in one directoryNote: Class.getResourceAsStream("plan.txt") with a class literal and string literal is auto-detected by native-image - no JSON needed for those cases.Resources from a Specific Module
{
"resources": [
{
"module": "library.module",
"glob": "resource-file.txt"
}
]
}Resource Bundles
Fixes MissingResourceException from ResourceBundle.getBundle(...).
{
"resources": [
{ "bundle": "com.example.Messages" },
{ "bundle": "com.example.Errors" }
]
}With a specific module:
{
"resources": [
{ "module": "app.module", "bundle": "com.example.Messages" }
]
}Bundles are included for all locales embedded in the image. To control locales:
native-image -Duser.country=US -Duser.language=en -H:IncludeLocales=fr,de
# or include everything (significantly increases image size):
native-image -H:+IncludeAllLocales---
6. Serialization Metadata
Fixes InvalidClassException, serialization StreamCorruptedException, or ClassNotFoundException during ObjectInputStream.readObject().
In JSON
{
"reflection": [
{
"type": "com.example.MySerializableClass",
"serializable": true
}
]
}Via Code (auto-detected)
If you use ObjectInputFilter, native-image detects this automatically when the pattern is a constant:
var filter = ObjectInputFilter.Config.createFilter("com.example.MyClass;!*;");
objectInputStream.setObjectInputFilter(filter);Proxy Serialization
{
"reflection": [
{
"type": {
"proxy": ["com.example.IFoo"],
"serializable": true
}
}
]
}---
7. Conditional Metadata Entries
Use conditions to avoid bloating the binary with metadata for code paths that may never run.
{
"condition": {
"typeReached": "com.example.FeatureModule"
},
"type": "com.example.OptionalClass",
"allDeclaredMethods": true
}The metadata for OptionalClass is only active at runtime once FeatureModule has been initialized. It is still included at build time if FeatureModule is reachable during static analysis.
A type is "reached" right before its static initializer runs, or when any of its subtypes are reached.
Use conditions liberally on third-party library metadata to keep binary size reasonable.
---
8. Full Sample reachability-metadata.json
{
"reflection": [
{
"condition": { "typeReached": "com.example.App" },
"type": "com.example.MyClass",
"fields": [
{ "name": "myField" }
],
"methods": [
{ "name": "myMethod", "parameterTypes": ["java.lang.String"] },
{ "name": "<init>", "parameterTypes": [] }
],
"allDeclaredConstructors": true,
"allPublicConstructors": true,
"allDeclaredFields": true,
"allPublicFields": true,
"allDeclaredMethods": true,
"allPublicMethods": true,
"unsafeAllocated": true,
"serializable": true
},
{
"type": {
"proxy": ["com.example.IFoo", "com.example.IBar"]
}
},
{
"type": "com.example.JniClass",
"jniAccessible": true,
"fields": [{ "name": "nativeHandle" }],
"allDeclaredMethods": true
}
],
"resources": [
{
"glob": "config/**"
},
{
"module": "app.module",
"glob": "static/index.html"
},
{
"bundle": "com.example.Messages"
}
]
}Sources
- https://github.com/oracle/graal/blob/master/substratevm/skills/building-native-image/references/reachability-metadata.md
- https://www.graalvm.org/latest/reference-manual/native-image/metadata/
Troubleshooting GraalVM Native Image
Overview
Use this skill to route Native Image build and runtime failures to the smallest relevant fix. Use reachability-metadata.md for missing reflection, JNI, proxy, resource, bundle, or serialization metadata.
Missing Reachability Metadata
If you encounter runtime errors related to reflection, JNI, resources, serialization, or dynamic proxies, consult reachability-metadata.md before attempting a fix.
Use that file for:
NoClassDefFoundErrororMissingReflectionRegistrationErrorMissingJNIRegistrationErrorMissingResourceExceptionfrom a missing resource bundle- Any user question about reflection, JNI, proxies, resources, resource bundles, or serialization in Native Image
For exact error reporting with GraalVM JDK 23+:
native-image --exact-reachability-metadata <class>For scoped exact metadata handling:
native-image --exact-reachability-metadata-path=<path> <class>Run the app with warning mode to see missing registrations without crashing:
java -XX:MissingRegistrationReportingMode=Warn -jar your-app.jarUse Exit mode during testing to catch errors hidden inside catch (Throwable t) blocks:
java -XX:MissingRegistrationReportingMode=Exit -jar your-app.jarFor GraalVM versions prior to JDK 23, use the build-time options -H:ThrowMissingRegistrationErrors= and -H:MissingRegistrationReportingMode=Warn instead.
It is not always necessary to add all reported elements to reachability-metadata.json. The element causing the program failure is usually among the last listed.
Classpath and Modules
If native-image cannot find your classes:
native-image -cp <path1>:<path2> <class>If using modules:
native-image -p <module-path> --add-modules <module-name> <class>Class Initialization and Linking
If a class fails because it initializes at build time but must not:
native-image --initialize-at-run-time=com.example.LazyClass <class>If a class must be initialized at build time:
native-image --initialize-at-build-time=com.example.EagerClass <class>If a type must be fully defined at build time:
native-image --link-at-build-time <class>Builder JVM and Memory
If the build runs out of memory:
native-image -J-Xmx8g <class>If you need to set a system property at build time:
native-image -Dkey=value <class>If you need to pass a flag to the JVM running the builder:
native-image -J<flag> <class>Diagnostics
If you want debug symbols in the binary:
native-image -g <class>If you want verbose build output:
native-image --verbose <class>If you want to inspect class initialization and substitutions:
native-image --diagnostics-mode <class>If you want a detailed HTML build report:
native-image --emit build-report <class>
# or: --emit build-report=report.htmlIf you want to trace instantiation of a specific class:
native-image --trace-object-instantiation=com.example.MyClass <class>If you want to see the native toolchain and build settings:
native-image --native-image-infoMaven Native Build Tools
"Could not resolve artifact"- EnsuremavenCentral()is in repositories and the version is correct."Could not find goal 'compile-no-fork'"- Verify<extensions>true</extensions>is set on the plugin.- Build runs without native compilation - Check you are activating the profile:
./mvnw -Pnative package. "No tests found" in native test- Ensure you declaremaven-surefire-plugin3.0+ in your build. If you use Maven Surefire prior to 3.0 M4 or your build forces an older JUnit Platform version, addjunit-platform-launcherto test dependencies.
If Maven native tests fail due to missing reflection or resource metadata, collect metadata using the tracing agent:
./mvnw -Pnative -Dagent=true test
./mvnw -Pnative native:metadata-copy
./mvnw -Pnative testGradle Native Build Tools
If the build fails with class initialization, linking errors, memory issues, or the binary behaves incorrectly at runtime, configure the relevant buildArgs, jvmArgs, or diagnostics in the graalvmNative block. See native-build-tools.md.
If Gradle native tests fail and you need the native test binary, the source location is:
build/native/nativeTestCompile/<imageName>Additional Run-Time Checks
Sometimes upgrading to the latest GraalVM version can resolve a run-time issue.
If the application code uses the java.home property, set it explicitly when running the native executable. Otherwise, System.getProperty("java.home") returns null.
./myapp -Djava.home=<path>For URL protocol support, see build-native-image.md. If the failure involves charset-sensitive behavior, add charset support at build time. This can increase binary size.
native-image -H:+AddAllCharsets <class>For locale-sensitive resource bundle behavior, see reachability-metadata.md. If the application uses security providers, pre-initialize them at build time:
native-image -H:AdditionalSecurityProviders=<list-of-providers> <class>For diagnosing native shared libraries, use missing-registration exit mode:
native-image -R:MissingRegistrationReportingMode=Exit <class>Sources
- https://github.com/oracle/graal/tree/master/substratevm/skills/building-native-image
- https://github.com/oracle/graal/tree/master/substratevm/skills/build-native-image-maven
- https://github.com/oracle/graal/tree/master/substratevm/skills/build-native-image-gradle
- https://www.graalvm.org/jdk25/reference-manual/native-image/guides/troubleshoot-run-time-errors/