diff --git a/docs/reference-manual/native-image/assets/skills/build-native-image-gradle/SKILL.md b/docs/reference-manual/native-image/assets/skills/build-native-image-gradle/SKILL.md new file mode 100644 index 000000000000..7226de322c1d --- /dev/null +++ b/docs/reference-manual/native-image/assets/skills/build-native-image-gradle/SKILL.md @@ -0,0 +1,56 @@ +--- +name: build-native-image-gradle +description: Build GraalVM native images using Gradle Native Build Tools. Use this skill to build Java applications with Gradle, configure native-image build.gradle settings, or resolve build or runtime issues. +--- + +# Gradle Native Image Build + +## Prerequisites +- Set `GRAALVM_HOME` to a GraalVM distribution. If not set, ask the user for the path. +- Apply the `application`, `java-library`, or `java` plugin along with `org.graalvm.buildtools.native`. + + +### Plugin Setup +Groovy DSL: +```groovy +plugins { + id 'application' + id 'org.graalvm.buildtools.native' version '0.11.1' +} +``` + +Kotlin DSL: +```kotlin +plugins { + application + id("org.graalvm.buildtools.native") version "0.11.1" +} +``` + + +## Build and Run +```bash +./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 image +``` + + +## Build or Runtime Failures +If the build fails with class initialization, linking errors, memory issues, or the binary behaves incorrectly at runtime, see [references/native-image-build-gradle-options.md](references/native-image-build-gradle-options.md). + + +## Native Testing +If `nativeTest` fails or you need to configure native JUnit tests or custom test suites, see [references/testing.md](references/testing.md). + + +## Missing Reachability Metadata +If a build or runtime error reports missing reflection, resource, serialization, or JNI registrations, see [references/reachability-metadata.md](references/reachability-metadata.md). + + +## Reference Files +| Topic | File | +|-------|------| +| DSL options and build arguments | [references/native-image-build-gradle-options.md](references/native-image-build-gradle-options.md) | +| Missing reachability metadata | [references/reachability-metadata.md](references/reachability-metadata.md) | +| Native testing | [references/testing.md](references/testing.md) | diff --git a/docs/reference-manual/native-image/assets/skills/build-native-image-gradle/references/native-image-build-gradle-options.md b/docs/reference-manual/native-image/assets/skills/build-native-image-gradle/references/native-image-build-gradle-options.md new file mode 100644 index 000000000000..ba047d44e80c --- /dev/null +++ b/docs/reference-manual/native-image/assets/skills/build-native-image-gradle/references/native-image-build-gradle-options.md @@ -0,0 +1,163 @@ +# Gradle Native Image Build Options + +## DSL Structure + +```groovy +graalvmNative { + binaries { + main { /* application binary options */ } + test { /* test binary options */ } + all { /* shared options */ } + } +} +``` + +## 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 | +| `fallback` | boolean | `false` | Allow JVM fallback if native build fails | +| `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 | + + +## Binary Configuration + +debug = true + +**Rename the output binary:** +```groovy +imageName = 'myapp' +``` + +**Set the entry point:** +```groovy +mainClass = 'com.example.Main' +``` + +**Enable debug info:** +```groovy +debug = true +// or use --debug-native +``` + +**Verbose build output:** +```groovy +verbose = true +``` + +**Faster builds (development):** +```groovy +quickBuild = true +// or use -Ob buildArg for maximum speed +buildArgs.add('-Ob') +``` + +**Build a shared library instead of an executable:** +```groovy +sharedLibrary = true +``` + + +## Build Failures and Errors + + +**Increase build memory:** +```groovy +jvmArgs.add('-Xmx8g') +``` + +**Force runtime initialization for a class:** +```groovy +buildArgs.add('--initialize-at-run-time=com.example.LazyClass') +``` + +**Force build-time initialization for a class:** +```groovy +buildArgs.add('--initialize-at-build-time=com.example.EagerClass') +``` + +**Inspect build diagnostics:** +```groovy +buildArgs.add('--diagnostics-mode') +``` + +## Resources + + +**Include resource files at runtime:** +```groovy +buildArgs.add('-H:IncludeResources=.*\\.(properties|xml)$') +``` + + +## Runtime Arguments + + +**Pass arguments to the application at startup:** +```groovy +runtimeArgs.add('--server.port=8080') +``` + + +## Full Example + +### Groovy DSL + +```groovy +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 + +```kotlin +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") + } + } +} +``` diff --git a/docs/reference-manual/native-image/assets/skills/build-native-image-gradle/references/reachability-metadata.md b/docs/reference-manual/native-image/assets/skills/build-native-image-gradle/references/reachability-metadata.md new file mode 100644 index 000000000000..015db5d4d1c7 --- /dev/null +++ b/docs/reference-manual/native-image/assets/skills/build-native-image-gradle/references/reachability-metadata.md @@ -0,0 +1,59 @@ +# Reachability Metadata for Gradle + +Use this guide to resolve native-image build failures caused by missing reachability metadata for reflection, resources, serialization, or JNI. Follow the workflow below to detect, collect, and manually add metadata as needed. + +## Detect Missing Metadata + +Add these options to your Gradle configuration to enable metadata checks and warnings: +```groovy +graalvmNative { + binaries.all { + buildArgs.add('--exact-reachability-metadata') + runtimeArgs.add('-XX:MissingRegistrationReportingMode=Warn') + } +} +``` + +## Resolution Workflow + +### Run the Tracing Agent + +Run the tracing agent to collect metadata: +```bash +./gradlew generateMetadata -Pcoordinates= -PagentAllowedPackages= +``` + +### Add Manual Metadata if Needed + +If the agent-collected metadata is incomplete, add manual configuration: + +Create `META-INF/native-image//manual-metadata/` and include only the files you need. Native Image automatically picks up metadata from this location. + +For metadata layout and file semantics, see the [Reachability Metadata documentation](https://www.graalvm.org/latest/reference-manual/native-image/metadata/). + +Minimal `reflect-config.json` example: + +```json +[ + { + "condition": { + "typeReachable": "com.example.Condition" + }, + "name": "com.example.Type", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] +``` + +## Rebuild and Verify + +Rebuild and test your project: +```bash +./gradlew nativeCompile +./gradlew nativeTest +``` diff --git a/docs/reference-manual/native-image/assets/skills/build-native-image-gradle/references/testing.md b/docs/reference-manual/native-image/assets/skills/build-native-image-gradle/references/testing.md new file mode 100644 index 000000000000..9011163b4aaa --- /dev/null +++ b/docs/reference-manual/native-image/assets/skills/build-native-image-gradle/references/testing.md @@ -0,0 +1,51 @@ +# Native Image Testing (Gradle) + +## Contents +- JUnit dependencies +- Running native tests +- Custom test suites + +## JUnit Dependencies + +```groovy +dependencies { + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' + testImplementation 'junit:junit:4.13.2' +} + +test { + useJUnitPlatform() +} +``` + + +## Running Native Tests + +```bash +./gradlew nativeTest +``` + + +The output binary is located at: +`build/native/nativeTestCompile/` + + + +## Custom Test Suites + + +Register additional test binaries for integration tests or other test source sets: + +```groovy +graalvmNative { + registerTestBinary("integTest") { + usingSourceSet(sourceSets.integTest) + forTestTask(tasks.named('integTest')) + } +} +``` + +This creates two tasks: +- `nativeIntegTestCompile` — builds the native test binary +- `nativeIntegTest` — runs it diff --git a/docs/reference-manual/native-image/assets/skills/build-native-image-maven/SKILL.md b/docs/reference-manual/native-image/assets/skills/build-native-image-maven/SKILL.md new file mode 100644 index 000000000000..cf27c657c604 --- /dev/null +++ b/docs/reference-manual/native-image/assets/skills/build-native-image-maven/SKILL.md @@ -0,0 +1,87 @@ +--- +name: build-native-image-maven +description: Build GraalVM native images using the native-maven-plugin (org.graalvm.buildtools). Use this skill to build Java applications with Maven, configure pom.xml native image settings, run native tests, collect metadata, or resolve build or runtime issues. +--- + +# Maven Native Image Build + +## Prerequisites +- Set `JAVA_HOME` to a JDK 17+ installation. +- Set `GRAALVM_HOME` to a GraalVM distribution. If not set, ask the user for the path. +- Use Maven 3.6+. + +## Plugin Setup +Add the following to your `pom.xml` inside a `native` profile: + +```xml + + + native + + + + org.graalvm.buildtools + native-maven-plugin + 0.11.1 + true + + + build-native + + compile-no-fork + + package + + + test-native + + test + + test + + + + org.example.Main + + + + + + +``` + + +## Build and Run +```bash +./mvnw -Pnative package # Build native image → target/ +./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 native +``` + + +## Plugin Not Resolving or Activating +- **"Could not resolve artifact"** — Ensure `mavenCentral()` is in repositories and the version is correct. +- **"Could not find goal 'compile-no-fork'"** — Verify `true` is set on the plugin. +- **Build runs without native compilation** — Check you are activating the profile: `./mvnw -Pnative package`. + + +## Build or Runtime Failures +For class initialization errors, linking issues, memory problems, or unexpected runtime behavior, see [references/maven-plugin-options.md](references/maven-plugin-options.md). + + +## Missing Reachability Metadata +When native-image reports missing reflection, resources, serialization, or JNI entries, see [references/reachability-metadata.md](references/reachability-metadata.md). + + +## Native Testing +For `nativeTest` failures or setting up native JUnit tests, see [references/testing.md](references/testing.md). + + +## Reference Files +| Topic | File | +|-------|------| +| Plugin configuration options | [references/maven-plugin-options.md](references/maven-plugin-options.md) | +| Missing reachability metadata | [references/reachability-metadata.md](references/reachability-metadata.md) | +| Native testing | [references/testing.md](references/testing.md) | diff --git a/docs/reference-manual/native-image/assets/skills/build-native-image-maven/references/maven-plugin-options.md b/docs/reference-manual/native-image/assets/skills/build-native-image-maven/references/maven-plugin-options.md new file mode 100644 index 000000000000..df5f659bf719 --- /dev/null +++ b/docs/reference-manual/native-image/assets/skills/build-native-image-maven/references/maven-plugin-options.md @@ -0,0 +1,144 @@ +# Maven Plugin Configuration Options + +## Contents +- Plugin goals +- Configuration options +- Build arguments +- Common buildArg flags +- Parent POM inheritance +- Shaded JAR support +- Full example + +## Configuration options + +| Option | Type | Default | Purpose | +|--------|------|---------|---------| +| `` | String | artifactId | Name of the output executable | +| `` | String | — | Entry point class (required) | +| `` | boolean | `false` | Generate debug info | +| `` | boolean | `false` | Enable verbose build output | +| `` | boolean | `false` | Allow fallback to JVM | +| `` | boolean | `false` | Build shared library instead of executable | +| `` | boolean | `false` | Faster build, lower runtime performance | +| `` | boolean | `true` | Use argument file for long classpaths | +| `` | boolean | `false` | Skip native compilation | +| `` | boolean | `false` | Skip native test execution | +| `` | List | empty | Arguments passed directly to `native-image` | +| `` | List | empty | JVM arguments for the native-image builder | +| `` | List | empty | Arguments passed to the app at runtime | +| `` | Map | empty | Environment variables during build | +| `` | Map | empty | System properties during build | +| `` | List | auto | Override classpath entries | +| `` | String | auto | Override classes directory | + +## Build arguments + +Pass any `native-image` flag via ``: + +```xml + + --initialize-at-run-time=com.example.LazyClass + -H:IncludeResources=.*\.xml$ + -O2 + +``` + +### Common buildArg flags + +**If a class must not initialize at build time:** +```xml +--initialize-at-run-time=<class-or-package> +``` + +**If a class must initialize at build time:** +```xml +--initialize-at-build-time=<class-or-package> +``` + +**If the build runs out of memory:** +```xml + + -Xmx8g + +``` + +**If you need to include resource files:** +```xml +-H:IncludeResources=.*\.(properties|xml)$ +``` + +**If you want to inspect build details:** +```xml +--diagnostics-mode +``` + +**If you want maximum performance (requires PGO, Oracle GraalVM only):** +```xml +-O3 +``` + +**If you want fastest build time (dev iteration):** +```xml +-Ob +``` + +**If you want a build report (Oracle GraalVM):** +```xml +--emit build-report +``` + +## Parent POM inheritance + +Child projects can append build arguments to a parent POM config using `combine.children`: + +```xml + + --verbose + +``` + +## Shaded JAR support + +If using `maven-shade-plugin`, point the native plugin to the shaded JAR: + +```xml + + false + + ${project.build.directory}/${project.artifactId}-${project.version}-shaded.jar + + +``` + +## Full example + +```xml + + org.graalvm.buildtools + native-maven-plugin + 0.11.1 + true + + + build-native + + compile-no-fork + + package + + + + myapp + com.example.Main + true + + --initialize-at-run-time=com.example.Lazy + -H:IncludeResources=.*\.properties$ + -O2 + + + -Xmx8g + + + +``` diff --git a/docs/reference-manual/native-image/assets/skills/build-native-image-maven/references/reachability-metadata.md b/docs/reference-manual/native-image/assets/skills/build-native-image-maven/references/reachability-metadata.md new file mode 100644 index 000000000000..0c244befada5 --- /dev/null +++ b/docs/reference-manual/native-image/assets/skills/build-native-image-maven/references/reachability-metadata.md @@ -0,0 +1,73 @@ +# Reachability Metadata for Maven + +Use this guide to resolve native-image build failures caused by missing reachability metadata for reflection, resources, serialization, or JNI. Follow the workflow below to detect, collect, and manually add metadata as needed. + +## Detect Missing Metadata + +Add these options to your Maven plugin configuration to enable metadata checks and warnings: +```xml + + + --exact-reachability-metadata + + + -XX:MissingRegistrationReportingMode=Warn + + +``` + +## Resolution Workflow + +### Run the Tracing Agent + +Run the tracing agent to collect metadata: +```bash +./mvnw -Pnative -Dagent=true test +./mvnw -Pnative native:metadata-copy +./mvnw -Pnative package +``` + +Configure metadata copy in your plugin: +```xml + + true + + + main + + true + META-INF/native-image + + +``` + +### Add Manual Metadata if Needed + +If the agent-collected metadata is incomplete, add manual configuration: + +Create `META-INF/native-image//manual-metadata/` and include only the files you need. Native Image automatically picks up metadata from this location. + +For metadata layout and file semantics, see the [Reachability Metadata documentation](https://www.graalvm.org/latest/reference-manual/native-image/metadata/). + +Minimal `reflect-config.json` example: + +```json +[ + { + "name": "com.example.MyClass", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true + } +] +``` + +## Rebuild and Verify + +Rebuild and test your project: +```bash +./mvnw -Pnative package +./mvnw -Pnative test +``` + +If a library still fails after repository, agent, and manual entries, capture the exact missing symbol from the error output and add only that entry. diff --git a/docs/reference-manual/native-image/assets/skills/build-native-image-maven/references/testing.md b/docs/reference-manual/native-image/assets/skills/build-native-image-maven/references/testing.md new file mode 100644 index 000000000000..6d26b1dcb0cb --- /dev/null +++ b/docs/reference-manual/native-image/assets/skills/build-native-image-maven/references/testing.md @@ -0,0 +1,102 @@ +# Native Image Testing (Maven) + +## Contents +- Required dependencies +- Plugin configuration for testing +- Running native tests +- Collecting test metadata +- Skip options +- Troubleshooting test failures + +## Required Dependencies + +```xml + + + org.junit.jupiter + junit-jupiter + 5.10.0 + test + + +``` + + +Also ensure you configure `maven-surefire-plugin` 3.0+: + +```xml + + org.apache.maven.plugins + maven-surefire-plugin + + +``` + + +## Plugin Configuration for Testing + + +Add the `test` goal execution to the native-maven-plugin: + +```xml + + test-native + + test + + test + +``` + +## Running Native Tests + +```bash +./mvnw -Pnative test +``` + +This compiles a native test binary and executes all discovered JUnit tests. + +## Collecting Test Metadata + + +If `nativeTest` fails due to missing reflection or resource metadata, collect it with the tracing agent: + +```bash +./mvnw -Pnative -Dagent=true test +./mvnw -Pnative native:metadata-copy +./mvnw -Pnative test +``` + +Configure the metadata copy to use the test output: + +```xml + + true + + META-INF/native-image + true + + main + + + +``` + + +## Skip Options + +| Flag | Effect | +|------|--------| +| `-DskipTests` | Skip all tests (JVM and native) | +| `-DskipNativeTests` | Run JVM tests only, skip native test compilation and execution | + + +## Troubleshooting Test Failures + + +**"No tests found" in native test** +Ensure you declare `maven-surefire-plugin` 3.0+ in your build. If you use Maven Surefire prior to 3.0 M4 or your build forces an older JUnit Platform version, add `junit-platform-launcher` to test dependencies. + + +**Tests pass on JVM but fail as native image** +Your test framework or dependencies use reflection not captured by metadata. Run `./mvnw -Pnative -Dagent=true test`, then `native:metadata-copy`, then retry. diff --git a/docs/reference-manual/native-image/assets/skills/building-native-image/SKILL.md b/docs/reference-manual/native-image/assets/skills/building-native-image/SKILL.md new file mode 100644 index 000000000000..56a2a2f3b8fe --- /dev/null +++ b/docs/reference-manual/native-image/assets/skills/building-native-image/SKILL.md @@ -0,0 +1,43 @@ +--- +name: building-native-image +description: Build and troubleshoot GraalVM Native Image applications. Use this skill to build Java applications with GraalVM Native Image, configure CLI options, or resolve build or runtime issues. +--- + +​# Building Native Image + +## Prerequisites +- Set `JAVA_HOME` to 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 +1. Compile your Java file with `javac`. +2. Build the Native Image: + ```bash + $JAVA_HOME/bin/native-image + ``` +3. Run the resulting executable: + ```bash + ./app-name + ``` +4. If Native Image cannot find your class file, set the classpath explicitly with the `-cp` option. +​ + +## Troubleshooting + +### Reachability Metadata +If you encounter runtime errors related to reflection, JNI, resources, serialization, or dynamic proxies, consult [`references/reachability-metadata.md`](references/reachability-metadata.md) before attempting a fix. Use this reference for: +- `NoClassDefFoundError` or `MissingReflectionRegistrationError` +- `MissingJNIRegistrationError` +- `MissingResourceException` (missing resource bundle) +- Any user question about reflection, JNI, proxies, resources, resource bundles, or serialization in Native Image. +​ + +## Native Image Options +To configure classpath, optimization level, output name, platform target, PGO, monitoring, or other CLI flags, see [`references/native-image-options.md`](references/native-image-options.md). + + +## Reference Files +| Topic | File | +|-------|------| +| Native Image CLI options | [references/native-image-options.md](references/native-image-options.md) | +| Missing reachability metadata | [references/reachability-metadata.md](references/reachability-metadata.md) | diff --git a/docs/reference-manual/native-image/assets/skills/building-native-image/references/native-image-options.md b/docs/reference-manual/native-image/assets/skills/building-native-image/references/native-image-options.md new file mode 100644 index 000000000000..118cd21ac03f --- /dev/null +++ b/docs/reference-manual/native-image/assets/skills/building-native-image/references/native-image-options.md @@ -0,0 +1,213 @@ +# GraalVM Native Image CLI Options + +## Classpath and modules + +**If native-image can't find your classes:** +```bash +native-image -cp : +``` + +**If using modules:** +```bash +native-image -p --add-modules +``` + +## Build failures + +**If a class fails because it initializes at build time but must not:** +```bash +native-image --initialize-at-run-time=com.example.LazyClass +``` + +**If a class must be initialized at build time:** +```bash +native-image --initialize-at-build-time=com.example.EagerClass +``` + +**If a type must be fully defined at build time:** +```bash +native-image --link-at-build-time +``` + +**If the build runs out of memory:** +```bash +native-image -J-Xmx8g +``` + +**If you need to set a system property at build time:** +```bash +native-image -Dkey=value +``` + +**If you need to pass a flag to the JVM running the builder:** +```bash +native-image -J +``` + +## Missing reachability metadata + +**If you want exact error reporting for missing reflection/JNI/proxy/resource/serialization registrations (GraalVM JDK 23+):** +```bash +native-image --exact-reachability-metadata +``` + +**If you want to scope exact metadata handling to specific classpath entries:** +```bash +native-image --exact-reachability-metadata-path= +``` + +## Output and binary type + +**If you want to rename the output binary:** +```bash +native-image -o myapp +``` + +**If you want to build a shared library:** +```bash +native-image --shared +``` + +**If you want a fully statically linked binary:** +```bash +native-image --static --libc=musl +``` + +**If you want static linking but keep libc dynamic:** +```bash +native-image --static-nolibc +``` + +## Performance and optimization + +**If you want fastest build time (dev iteration):** +```bash +native-image -Ob +``` + +**If you want best runtime performance:** +```bash +native-image -O3 # or combine with --pgo +``` + +**If you want to optimize for binary size:** +```bash +native-image -Os +``` + +**If you want to collect PGO profile data:** +```bash +native-image --pgo-instrument +./myapp # run to collect profile +native-image --pgo=default.iprof +``` + +**If you want to change the garbage collector:** +```bash +native-image --gc=G1 # G1 (GraalVM EE only) +native-image --gc=epsilon # no GC (throughput) +native-image --gc=serial # default +``` + +**If you want to target the current machine's CPU features:** +```bash +native-image -march=native +``` + +**If you need maximum compatibility across machines:** +```bash +native-image -march=compatibility +``` + +**If you want to limit build parallelism:** +```bash +native-image --parallelism=4 +``` + +## Debugging and diagnostics + +**If you want debug symbols in the binary:** +```bash +native-image -g +``` + +**If you want verbose build output:** +```bash +native-image --verbose +``` + +**If you want to inspect class initialization and substitutions:** +```bash +native-image --diagnostics-mode +``` + +**If you want a detailed HTML build report:** +```bash +native-image --emit build-report +# or: --emit build-report=report.html +``` + +**If you want to trace instantiation of a specific class:** +```bash +native-image --trace-object-instantiation=com.example.MyClass +``` + +## Network support + +**If the binary needs HTTP/HTTPS:** +```bash +native-image --enable-http --enable-https +``` + +**If the binary needs specific URL protocols:** +```bash +native-image --enable-url-protocols=http,https +``` + +## Monitoring and observability + +**If you need runtime monitoring (heap dumps, JFR, thread dumps):** +```bash +native-image --enable-monitoring=heapdump,jfr,threaddump +``` + +## Security and compliance + +**If you need all security services (e.g. TLS/SSL):** +```bash +native-image --enable-all-security-services +``` + +**If you need a Software Bill of Materials (SBOM):** +```bash +native-image --enable-sbom=embed,export +``` + +## Cross-compilation and platform + +**If you need to cross-compile for a different OS/arch:** +```bash +native-image --target=linux-aarch64 +``` + +**If you need a custom C compiler:** +```bash +native-image --native-compiler-path=/usr/bin/gcc +``` + +## Info and discovery + +**If you want to list available CPU features:** +```bash +native-image --list-cpu-features +``` + +**If you want to list observable modules:** +```bash +native-image --list-modules +``` + +**If you want to see the native toolchain and build settings:** +```bash +native-image --native-image-info +``` diff --git a/docs/reference-manual/native-image/assets/skills/building-native-image/references/reachability-metadata.md b/docs/reference-manual/native-image/assets/skills/building-native-image/references/reachability-metadata.md new file mode 100644 index 000000000000..ead39d49b6d0 --- /dev/null +++ b/docs/reference-manual/native-image/assets/skills/building-native-image/references/reachability-metadata.md @@ -0,0 +1,409 @@ +# Reachability Metadata GraalVM Native Image + +## Table of Contents + +1. [Diagnosing the Error Type](#1-diagnosing-the-error-type) +2. [Where to Put Metadata Files](#2-where-to-put-metadata-files) +3. [Reflection Metadata](#3-reflection-metadata) +4. [JNI Metadata](#4-jni-metadata) +5. [Resource Metadata](#5-resource-metadata) +6. [Serialization Metadata](#6-serialization-metadata) +7. [Conditional Metadata Entries](#7-conditional-metadata-entries) +8. [Debugging Tips](#8-debugging-tips) +9. [Full Sample reachability-metadata.json](#9-full-sample-reachability-metadatajson) + + +## 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](#4-reflection-metadata) - register the type | +| `MissingReflectionRegistrationError` | Reflective access to unregistered class/method/field | [Reflection Metadata](#4-reflection-metadata) | +| `NoSuchMethodException` | Method not registered for reflective invocation | [Reflection Metadata - Methods](#methods) | +| `NoSuchFieldException` | Field not registered for reflective access | [Reflection Metadata - Fields](#fields) | +| `MissingJNIRegistrationError` | JNI lookup of unregistered type/member | [JNI Metadata](#5-jni-metadata) | +| `MissingForeignRegistrationError` | FFM downcall/upcall without registered descriptor | Foreign section (advanced, see GraalVM docs) | +| `MissingResourceException` | Resource bundle not included | [Resource Metadata - Bundles](#resource-bundles) | + + +**Quick diagnostic command** - run the app with warning mode to see all missing registrations without crashing: +```shell +java -XX:MissingRegistrationReportingMode=Warn -jar your-app.jar +``` +Use `Exit` mode during testing to catch errors hidden inside `catch (Throwable t)` blocks: +```shell +java -XX:MissingRegistrationReportingMode=Exit -jar your-app.jar +``` +Enable strict metadata mode at build time: +```shell +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/ + └── / + └── / + └── reachability-metadata.json +``` + +The file contains a top-level object with one key per metadata type: +```json +{ + "reflection": [], + "resources": [] +} +``` + +> **Alternative approaches (when JSON isn't enough):** +> - Pass constant arguments to `Class.forName("Foo")`, `getMethod(...)`, etc. - native-image evaluates these at build time automatically. +> - Use `-H:Preserve=` to preserve entire packages. + +--- + +## 3. Reflection Metadata + +### Register a Type (fixes `NoClassDefFoundError`, `MissingReflectionRegistrationError`) + +```json +{ + "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:** +```json +{ + "type": "com.example.MyClass", + "methods": [ + { "name": "myMethod", "parameterTypes": ["java.lang.String", "int"] }, + { "name": "", "parameterTypes": [] } + ] +} +``` +> Use `""` for constructors. + +**Register all methods (less precise, larger binary):** +```json +{ + "type": "com.example.MyClass", + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allPublicConstructors": true +} +``` +- `allDeclared*` - methods/constructors declared directly on this type +- `allPublic*` - all public methods/constructors including those inherited from supertypes + +### Fields + +Fixes `NoSuchFieldException` and `MissingReflectionRegistrationError` on `Field.get()` / `Field.set()`. + +**Register specific fields:** +```json +{ + "type": "com.example.MyClass", + "fields": [ + { "name": "myField" }, + { "name": "anotherField" } + ] +} +``` + +**Register all fields:** +```json +{ + "type": "com.example.MyClass", + "allDeclaredFields": true, + "allPublicFields": true +} +``` + +### Dynamic Proxies + +For classes obtained via `Proxy.newProxyInstance(...)` - the type is the proxy's interface list: +```json +{ + "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)`: +```json +{ + "type": "com.example.MyClass", + "unsafeAllocated": true +} +``` + +### Full Type Entry Reference + +```json +{ + "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-metadata` with `-XX:MissingRegistrationReportingMode=Warn` to see what's missing. + +**Register a JNI-accessible type:** +```json +{ + "reflection": [ + { + "type": "com.example.MyClass", + "jniAccessible": true + } + ] +} +``` + +**Add fields and methods for JNI access:** +```json +{ + "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: + +```json +{ + "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:** +```json +{ "glob": "config/app.properties" } // exact file +{ "glob": "**/**.json" } // all JSON files anywhere +{ "glob": "static/images/*.png" } // all PNGs in one directory +``` + +> **Note:** `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 + +```json +{ + "resources": [ + { + "module": "library.module", + "glob": "resource-file.txt" + } + ] +} +``` + +### Resource Bundles + +Fixes `MissingResourceException` from `ResourceBundle.getBundle(...)`. + +```json +{ + "resources": [ + { "bundle": "com.example.Messages" }, + { "bundle": "com.example.Errors" } + ] +} +``` + +With a specific module: +```json +{ + "resources": [ + { "module": "app.module", "bundle": "com.example.Messages" } + ] +} +``` + +Bundles are included for all locales embedded in the image. To control locales: +```shell +native-image -Duser.country=US -Duser.language=en -H:IncludeLocales=fr,de +# or include everything: +native-image -H:+IncludeAllLocales +``` + +--- + +## 6. Serialization Metadata + +Fixes `InvalidClassException`, serialization `StreamCorruptedException`, or `ClassNotFoundException` during `ObjectInputStream.readObject()`. + +### In JSON + +```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: +```java +var filter = ObjectInputFilter.Config.createFilter("com.example.MyClass;!*;"); +objectInputStream.setObjectInputFilter(filter); +``` + +### Proxy Serialization + +```json +{ + "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. + +```json +{ + "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. + +--- + +## 9. Full Sample reachability-metadata.json + +```json +{ + "reflection": [ + { + "condition": { "typeReached": "com.example.App" }, + "type": "com.example.MyClass", + "fields": [ + { "name": "myField" } + ], + "methods": [ + { "name": "myMethod", "parameterTypes": ["java.lang.String"] }, + { "name": "", "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" + } + ] +} +``` \ No newline at end of file diff --git a/substratevm/mx.substratevm/mx_substratevm.py b/substratevm/mx.substratevm/mx_substratevm.py index 004915e66747..5b4617ee5bf3 100644 --- a/substratevm/mx.substratevm/mx_substratevm.py +++ b/substratevm/mx.substratevm/mx_substratevm.py @@ -23,6 +23,7 @@ # questions. # +import filecmp import os import pathlib import platform @@ -121,6 +122,47 @@ def svmbuild_dir(suite=None): out_root = suite.get_output_root() return join(out_root, 'svmbuild') + +def _abort_if_skills_are_not_synchronized(): + repo_root = pathlib.Path(suite.dir).parent.resolve() + substrate_skills_dir = pathlib.Path(os.path.join(suite.dir, 'skills')).resolve() + docs_skills_dir = pathlib.Path(os.path.join(suite.dir, '..', 'docs', 'reference-manual', 'native-image', 'assets', 'skills')).resolve() + + missing_dirs = [str(path) for path in (substrate_skills_dir, docs_skills_dir) if not path.is_dir()] + if missing_dirs: + mx.abort('Could not verify synchronized skills directories:\n ' + '\n '.join(missing_dirs)) + + def _relative_files(root): + return {path.relative_to(root).as_posix() for path in root.rglob('*') if path.is_file()} + + substrate_files = _relative_files(substrate_skills_dir) + docs_files = _relative_files(docs_skills_dir) + + only_in_substrate = sorted(substrate_files - docs_files) + only_in_docs = sorted(docs_files - substrate_files) + mismatched_files = sorted( + rel_path for rel_path in substrate_files & docs_files + if not filecmp.cmp(substrate_skills_dir / rel_path, docs_skills_dir / rel_path, shallow=False) + ) + + if only_in_substrate or only_in_docs or mismatched_files: + substrate_skills_rel = os.path.relpath(substrate_skills_dir, repo_root) + docs_skills_rel = os.path.relpath(docs_skills_dir, repo_root) + details = [] + if only_in_substrate: + details.append(f'Only in {substrate_skills_rel}:\n ' + '\n '.join(only_in_substrate)) + if only_in_docs: + details.append(f'Only in {docs_skills_rel}:\n ' + '\n '.join(only_in_docs)) + if mismatched_files: + details.append('Different file contents:\n ' + '\n '.join(mismatched_files)) + mx.abort( + 'The skills shipped with Graal must stay synchronized with the Native Image reference manual assets.\n' + 'Sync these directories:\n' + f' {substrate_skills_dir}\n' + f' {docs_skills_dir}\n' + + '\n'.join(details) + ) + def is_musl_supported(): jdk = get_jdk() if mx.is_linux() and mx.get_arch() == "amd64" and jdk.javaCompliance == '11': @@ -547,6 +589,10 @@ def help_stdout_check(output): schemas_dir = os.path.join(suite.dir, '..', 'docs', 'reference-manual', 'native-image', 'assets') mx_sdk.validate_dir_files_with_file_schema_pairs(schemas_dir, svmbuild_dir(), json_and_schema_file_pairs) + with Task('Validate synchronized skills assets', tasks, tags=[GraalTags.helloworld]) as t: + if t: + _abort_if_skills_are_not_synchronized() + with Task('java agent tests', tasks, tags=[GraalTags.java_agent]) as t: if t: java_agent_test(args.extra_image_builder_arguments) @@ -3020,5 +3066,4 @@ def apply(self, config): return (vmArgs, mainClass, mainClassArgs) - mx_unittest.register_unittest_config(StandalonePointstoUnittestsConfig()) diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index cb98df9e1183..710bb96fb1a8 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -2755,6 +2755,7 @@ "builder/clibraries/" : ["extracted-dependency:substratevm:SVM_HOSTED_NATIVE"], "builder/lib/" : ["dependency:com.oracle.svm.native.reporterchelper"], "schemas/reachability-metadata-schema.json" : ["file:schemas/reachability-metadata-schema-v1.2.0.json"], + "skills/" : ["file:skills/*"], # Note: `ld64.lld` is a symlink to `lld`, but it is dereferenced here. "bin/" : ["extracted-dependency:LLVM_LLD_STANDALONE/bin/ld64.lld"], }, diff --git a/substratevm/skills/build-native-image-gradle/SKILL.md b/substratevm/skills/build-native-image-gradle/SKILL.md new file mode 100644 index 000000000000..7226de322c1d --- /dev/null +++ b/substratevm/skills/build-native-image-gradle/SKILL.md @@ -0,0 +1,56 @@ +--- +name: build-native-image-gradle +description: Build GraalVM native images using Gradle Native Build Tools. Use this skill to build Java applications with Gradle, configure native-image build.gradle settings, or resolve build or runtime issues. +--- + +# Gradle Native Image Build + +## Prerequisites +- Set `GRAALVM_HOME` to a GraalVM distribution. If not set, ask the user for the path. +- Apply the `application`, `java-library`, or `java` plugin along with `org.graalvm.buildtools.native`. + + +### Plugin Setup +Groovy DSL: +```groovy +plugins { + id 'application' + id 'org.graalvm.buildtools.native' version '0.11.1' +} +``` + +Kotlin DSL: +```kotlin +plugins { + application + id("org.graalvm.buildtools.native") version "0.11.1" +} +``` + + +## Build and Run +```bash +./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 image +``` + + +## Build or Runtime Failures +If the build fails with class initialization, linking errors, memory issues, or the binary behaves incorrectly at runtime, see [references/native-image-build-gradle-options.md](references/native-image-build-gradle-options.md). + + +## Native Testing +If `nativeTest` fails or you need to configure native JUnit tests or custom test suites, see [references/testing.md](references/testing.md). + + +## Missing Reachability Metadata +If a build or runtime error reports missing reflection, resource, serialization, or JNI registrations, see [references/reachability-metadata.md](references/reachability-metadata.md). + + +## Reference Files +| Topic | File | +|-------|------| +| DSL options and build arguments | [references/native-image-build-gradle-options.md](references/native-image-build-gradle-options.md) | +| Missing reachability metadata | [references/reachability-metadata.md](references/reachability-metadata.md) | +| Native testing | [references/testing.md](references/testing.md) | diff --git a/substratevm/skills/build-native-image-gradle/references/native-image-build-gradle-options.md b/substratevm/skills/build-native-image-gradle/references/native-image-build-gradle-options.md new file mode 100644 index 000000000000..ba047d44e80c --- /dev/null +++ b/substratevm/skills/build-native-image-gradle/references/native-image-build-gradle-options.md @@ -0,0 +1,163 @@ +# Gradle Native Image Build Options + +## DSL Structure + +```groovy +graalvmNative { + binaries { + main { /* application binary options */ } + test { /* test binary options */ } + all { /* shared options */ } + } +} +``` + +## 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 | +| `fallback` | boolean | `false` | Allow JVM fallback if native build fails | +| `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 | + + +## Binary Configuration + +debug = true + +**Rename the output binary:** +```groovy +imageName = 'myapp' +``` + +**Set the entry point:** +```groovy +mainClass = 'com.example.Main' +``` + +**Enable debug info:** +```groovy +debug = true +// or use --debug-native +``` + +**Verbose build output:** +```groovy +verbose = true +``` + +**Faster builds (development):** +```groovy +quickBuild = true +// or use -Ob buildArg for maximum speed +buildArgs.add('-Ob') +``` + +**Build a shared library instead of an executable:** +```groovy +sharedLibrary = true +``` + + +## Build Failures and Errors + + +**Increase build memory:** +```groovy +jvmArgs.add('-Xmx8g') +``` + +**Force runtime initialization for a class:** +```groovy +buildArgs.add('--initialize-at-run-time=com.example.LazyClass') +``` + +**Force build-time initialization for a class:** +```groovy +buildArgs.add('--initialize-at-build-time=com.example.EagerClass') +``` + +**Inspect build diagnostics:** +```groovy +buildArgs.add('--diagnostics-mode') +``` + +## Resources + + +**Include resource files at runtime:** +```groovy +buildArgs.add('-H:IncludeResources=.*\\.(properties|xml)$') +``` + + +## Runtime Arguments + + +**Pass arguments to the application at startup:** +```groovy +runtimeArgs.add('--server.port=8080') +``` + + +## Full Example + +### Groovy DSL + +```groovy +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 + +```kotlin +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") + } + } +} +``` diff --git a/substratevm/skills/build-native-image-gradle/references/reachability-metadata.md b/substratevm/skills/build-native-image-gradle/references/reachability-metadata.md new file mode 100644 index 000000000000..015db5d4d1c7 --- /dev/null +++ b/substratevm/skills/build-native-image-gradle/references/reachability-metadata.md @@ -0,0 +1,59 @@ +# Reachability Metadata for Gradle + +Use this guide to resolve native-image build failures caused by missing reachability metadata for reflection, resources, serialization, or JNI. Follow the workflow below to detect, collect, and manually add metadata as needed. + +## Detect Missing Metadata + +Add these options to your Gradle configuration to enable metadata checks and warnings: +```groovy +graalvmNative { + binaries.all { + buildArgs.add('--exact-reachability-metadata') + runtimeArgs.add('-XX:MissingRegistrationReportingMode=Warn') + } +} +``` + +## Resolution Workflow + +### Run the Tracing Agent + +Run the tracing agent to collect metadata: +```bash +./gradlew generateMetadata -Pcoordinates= -PagentAllowedPackages= +``` + +### Add Manual Metadata if Needed + +If the agent-collected metadata is incomplete, add manual configuration: + +Create `META-INF/native-image//manual-metadata/` and include only the files you need. Native Image automatically picks up metadata from this location. + +For metadata layout and file semantics, see the [Reachability Metadata documentation](https://www.graalvm.org/latest/reference-manual/native-image/metadata/). + +Minimal `reflect-config.json` example: + +```json +[ + { + "condition": { + "typeReachable": "com.example.Condition" + }, + "name": "com.example.Type", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + } +] +``` + +## Rebuild and Verify + +Rebuild and test your project: +```bash +./gradlew nativeCompile +./gradlew nativeTest +``` diff --git a/substratevm/skills/build-native-image-gradle/references/testing.md b/substratevm/skills/build-native-image-gradle/references/testing.md new file mode 100644 index 000000000000..9011163b4aaa --- /dev/null +++ b/substratevm/skills/build-native-image-gradle/references/testing.md @@ -0,0 +1,51 @@ +# Native Image Testing (Gradle) + +## Contents +- JUnit dependencies +- Running native tests +- Custom test suites + +## JUnit Dependencies + +```groovy +dependencies { + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' + testImplementation 'junit:junit:4.13.2' +} + +test { + useJUnitPlatform() +} +``` + + +## Running Native Tests + +```bash +./gradlew nativeTest +``` + + +The output binary is located at: +`build/native/nativeTestCompile/` + + + +## Custom Test Suites + + +Register additional test binaries for integration tests or other test source sets: + +```groovy +graalvmNative { + registerTestBinary("integTest") { + usingSourceSet(sourceSets.integTest) + forTestTask(tasks.named('integTest')) + } +} +``` + +This creates two tasks: +- `nativeIntegTestCompile` — builds the native test binary +- `nativeIntegTest` — runs it diff --git a/substratevm/skills/build-native-image-maven/SKILL.md b/substratevm/skills/build-native-image-maven/SKILL.md new file mode 100644 index 000000000000..cf27c657c604 --- /dev/null +++ b/substratevm/skills/build-native-image-maven/SKILL.md @@ -0,0 +1,87 @@ +--- +name: build-native-image-maven +description: Build GraalVM native images using the native-maven-plugin (org.graalvm.buildtools). Use this skill to build Java applications with Maven, configure pom.xml native image settings, run native tests, collect metadata, or resolve build or runtime issues. +--- + +# Maven Native Image Build + +## Prerequisites +- Set `JAVA_HOME` to a JDK 17+ installation. +- Set `GRAALVM_HOME` to a GraalVM distribution. If not set, ask the user for the path. +- Use Maven 3.6+. + +## Plugin Setup +Add the following to your `pom.xml` inside a `native` profile: + +```xml + + + native + + + + org.graalvm.buildtools + native-maven-plugin + 0.11.1 + true + + + build-native + + compile-no-fork + + package + + + test-native + + test + + test + + + + org.example.Main + + + + + + +``` + + +## Build and Run +```bash +./mvnw -Pnative package # Build native image → target/ +./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 native +``` + + +## Plugin Not Resolving or Activating +- **"Could not resolve artifact"** — Ensure `mavenCentral()` is in repositories and the version is correct. +- **"Could not find goal 'compile-no-fork'"** — Verify `true` is set on the plugin. +- **Build runs without native compilation** — Check you are activating the profile: `./mvnw -Pnative package`. + + +## Build or Runtime Failures +For class initialization errors, linking issues, memory problems, or unexpected runtime behavior, see [references/maven-plugin-options.md](references/maven-plugin-options.md). + + +## Missing Reachability Metadata +When native-image reports missing reflection, resources, serialization, or JNI entries, see [references/reachability-metadata.md](references/reachability-metadata.md). + + +## Native Testing +For `nativeTest` failures or setting up native JUnit tests, see [references/testing.md](references/testing.md). + + +## Reference Files +| Topic | File | +|-------|------| +| Plugin configuration options | [references/maven-plugin-options.md](references/maven-plugin-options.md) | +| Missing reachability metadata | [references/reachability-metadata.md](references/reachability-metadata.md) | +| Native testing | [references/testing.md](references/testing.md) | diff --git a/substratevm/skills/build-native-image-maven/references/maven-plugin-options.md b/substratevm/skills/build-native-image-maven/references/maven-plugin-options.md new file mode 100644 index 000000000000..df5f659bf719 --- /dev/null +++ b/substratevm/skills/build-native-image-maven/references/maven-plugin-options.md @@ -0,0 +1,144 @@ +# Maven Plugin Configuration Options + +## Contents +- Plugin goals +- Configuration options +- Build arguments +- Common buildArg flags +- Parent POM inheritance +- Shaded JAR support +- Full example + +## Configuration options + +| Option | Type | Default | Purpose | +|--------|------|---------|---------| +| `` | String | artifactId | Name of the output executable | +| `` | String | — | Entry point class (required) | +| `` | boolean | `false` | Generate debug info | +| `` | boolean | `false` | Enable verbose build output | +| `` | boolean | `false` | Allow fallback to JVM | +| `` | boolean | `false` | Build shared library instead of executable | +| `` | boolean | `false` | Faster build, lower runtime performance | +| `` | boolean | `true` | Use argument file for long classpaths | +| `` | boolean | `false` | Skip native compilation | +| `` | boolean | `false` | Skip native test execution | +| `` | List | empty | Arguments passed directly to `native-image` | +| `` | List | empty | JVM arguments for the native-image builder | +| `` | List | empty | Arguments passed to the app at runtime | +| `` | Map | empty | Environment variables during build | +| `` | Map | empty | System properties during build | +| `` | List | auto | Override classpath entries | +| `` | String | auto | Override classes directory | + +## Build arguments + +Pass any `native-image` flag via ``: + +```xml + + --initialize-at-run-time=com.example.LazyClass + -H:IncludeResources=.*\.xml$ + -O2 + +``` + +### Common buildArg flags + +**If a class must not initialize at build time:** +```xml +--initialize-at-run-time=<class-or-package> +``` + +**If a class must initialize at build time:** +```xml +--initialize-at-build-time=<class-or-package> +``` + +**If the build runs out of memory:** +```xml + + -Xmx8g + +``` + +**If you need to include resource files:** +```xml +-H:IncludeResources=.*\.(properties|xml)$ +``` + +**If you want to inspect build details:** +```xml +--diagnostics-mode +``` + +**If you want maximum performance (requires PGO, Oracle GraalVM only):** +```xml +-O3 +``` + +**If you want fastest build time (dev iteration):** +```xml +-Ob +``` + +**If you want a build report (Oracle GraalVM):** +```xml +--emit build-report +``` + +## Parent POM inheritance + +Child projects can append build arguments to a parent POM config using `combine.children`: + +```xml + + --verbose + +``` + +## Shaded JAR support + +If using `maven-shade-plugin`, point the native plugin to the shaded JAR: + +```xml + + false + + ${project.build.directory}/${project.artifactId}-${project.version}-shaded.jar + + +``` + +## Full example + +```xml + + org.graalvm.buildtools + native-maven-plugin + 0.11.1 + true + + + build-native + + compile-no-fork + + package + + + + myapp + com.example.Main + true + + --initialize-at-run-time=com.example.Lazy + -H:IncludeResources=.*\.properties$ + -O2 + + + -Xmx8g + + + +``` diff --git a/substratevm/skills/build-native-image-maven/references/reachability-metadata.md b/substratevm/skills/build-native-image-maven/references/reachability-metadata.md new file mode 100644 index 000000000000..0c244befada5 --- /dev/null +++ b/substratevm/skills/build-native-image-maven/references/reachability-metadata.md @@ -0,0 +1,73 @@ +# Reachability Metadata for Maven + +Use this guide to resolve native-image build failures caused by missing reachability metadata for reflection, resources, serialization, or JNI. Follow the workflow below to detect, collect, and manually add metadata as needed. + +## Detect Missing Metadata + +Add these options to your Maven plugin configuration to enable metadata checks and warnings: +```xml + + + --exact-reachability-metadata + + + -XX:MissingRegistrationReportingMode=Warn + + +``` + +## Resolution Workflow + +### Run the Tracing Agent + +Run the tracing agent to collect metadata: +```bash +./mvnw -Pnative -Dagent=true test +./mvnw -Pnative native:metadata-copy +./mvnw -Pnative package +``` + +Configure metadata copy in your plugin: +```xml + + true + + + main + + true + META-INF/native-image + + +``` + +### Add Manual Metadata if Needed + +If the agent-collected metadata is incomplete, add manual configuration: + +Create `META-INF/native-image//manual-metadata/` and include only the files you need. Native Image automatically picks up metadata from this location. + +For metadata layout and file semantics, see the [Reachability Metadata documentation](https://www.graalvm.org/latest/reference-manual/native-image/metadata/). + +Minimal `reflect-config.json` example: + +```json +[ + { + "name": "com.example.MyClass", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true + } +] +``` + +## Rebuild and Verify + +Rebuild and test your project: +```bash +./mvnw -Pnative package +./mvnw -Pnative test +``` + +If a library still fails after repository, agent, and manual entries, capture the exact missing symbol from the error output and add only that entry. diff --git a/substratevm/skills/build-native-image-maven/references/testing.md b/substratevm/skills/build-native-image-maven/references/testing.md new file mode 100644 index 000000000000..6d26b1dcb0cb --- /dev/null +++ b/substratevm/skills/build-native-image-maven/references/testing.md @@ -0,0 +1,102 @@ +# Native Image Testing (Maven) + +## Contents +- Required dependencies +- Plugin configuration for testing +- Running native tests +- Collecting test metadata +- Skip options +- Troubleshooting test failures + +## Required Dependencies + +```xml + + + org.junit.jupiter + junit-jupiter + 5.10.0 + test + + +``` + + +Also ensure you configure `maven-surefire-plugin` 3.0+: + +```xml + + org.apache.maven.plugins + maven-surefire-plugin + + +``` + + +## Plugin Configuration for Testing + + +Add the `test` goal execution to the native-maven-plugin: + +```xml + + test-native + + test + + test + +``` + +## Running Native Tests + +```bash +./mvnw -Pnative test +``` + +This compiles a native test binary and executes all discovered JUnit tests. + +## Collecting Test Metadata + + +If `nativeTest` fails due to missing reflection or resource metadata, collect it with the tracing agent: + +```bash +./mvnw -Pnative -Dagent=true test +./mvnw -Pnative native:metadata-copy +./mvnw -Pnative test +``` + +Configure the metadata copy to use the test output: + +```xml + + true + + META-INF/native-image + true + + main + + + +``` + + +## Skip Options + +| Flag | Effect | +|------|--------| +| `-DskipTests` | Skip all tests (JVM and native) | +| `-DskipNativeTests` | Run JVM tests only, skip native test compilation and execution | + + +## Troubleshooting Test Failures + + +**"No tests found" in native test** +Ensure you declare `maven-surefire-plugin` 3.0+ in your build. If you use Maven Surefire prior to 3.0 M4 or your build forces an older JUnit Platform version, add `junit-platform-launcher` to test dependencies. + + +**Tests pass on JVM but fail as native image** +Your test framework or dependencies use reflection not captured by metadata. Run `./mvnw -Pnative -Dagent=true test`, then `native:metadata-copy`, then retry. diff --git a/substratevm/skills/building-native-image/SKILL.md b/substratevm/skills/building-native-image/SKILL.md new file mode 100644 index 000000000000..56a2a2f3b8fe --- /dev/null +++ b/substratevm/skills/building-native-image/SKILL.md @@ -0,0 +1,43 @@ +--- +name: building-native-image +description: Build and troubleshoot GraalVM Native Image applications. Use this skill to build Java applications with GraalVM Native Image, configure CLI options, or resolve build or runtime issues. +--- + +​# Building Native Image + +## Prerequisites +- Set `JAVA_HOME` to 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 +1. Compile your Java file with `javac`. +2. Build the Native Image: + ```bash + $JAVA_HOME/bin/native-image + ``` +3. Run the resulting executable: + ```bash + ./app-name + ``` +4. If Native Image cannot find your class file, set the classpath explicitly with the `-cp` option. +​ + +## Troubleshooting + +### Reachability Metadata +If you encounter runtime errors related to reflection, JNI, resources, serialization, or dynamic proxies, consult [`references/reachability-metadata.md`](references/reachability-metadata.md) before attempting a fix. Use this reference for: +- `NoClassDefFoundError` or `MissingReflectionRegistrationError` +- `MissingJNIRegistrationError` +- `MissingResourceException` (missing resource bundle) +- Any user question about reflection, JNI, proxies, resources, resource bundles, or serialization in Native Image. +​ + +## Native Image Options +To configure classpath, optimization level, output name, platform target, PGO, monitoring, or other CLI flags, see [`references/native-image-options.md`](references/native-image-options.md). + + +## Reference Files +| Topic | File | +|-------|------| +| Native Image CLI options | [references/native-image-options.md](references/native-image-options.md) | +| Missing reachability metadata | [references/reachability-metadata.md](references/reachability-metadata.md) | diff --git a/substratevm/skills/building-native-image/references/native-image-options.md b/substratevm/skills/building-native-image/references/native-image-options.md new file mode 100644 index 000000000000..118cd21ac03f --- /dev/null +++ b/substratevm/skills/building-native-image/references/native-image-options.md @@ -0,0 +1,213 @@ +# GraalVM Native Image CLI Options + +## Classpath and modules + +**If native-image can't find your classes:** +```bash +native-image -cp : +``` + +**If using modules:** +```bash +native-image -p --add-modules +``` + +## Build failures + +**If a class fails because it initializes at build time but must not:** +```bash +native-image --initialize-at-run-time=com.example.LazyClass +``` + +**If a class must be initialized at build time:** +```bash +native-image --initialize-at-build-time=com.example.EagerClass +``` + +**If a type must be fully defined at build time:** +```bash +native-image --link-at-build-time +``` + +**If the build runs out of memory:** +```bash +native-image -J-Xmx8g +``` + +**If you need to set a system property at build time:** +```bash +native-image -Dkey=value +``` + +**If you need to pass a flag to the JVM running the builder:** +```bash +native-image -J +``` + +## Missing reachability metadata + +**If you want exact error reporting for missing reflection/JNI/proxy/resource/serialization registrations (GraalVM JDK 23+):** +```bash +native-image --exact-reachability-metadata +``` + +**If you want to scope exact metadata handling to specific classpath entries:** +```bash +native-image --exact-reachability-metadata-path= +``` + +## Output and binary type + +**If you want to rename the output binary:** +```bash +native-image -o myapp +``` + +**If you want to build a shared library:** +```bash +native-image --shared +``` + +**If you want a fully statically linked binary:** +```bash +native-image --static --libc=musl +``` + +**If you want static linking but keep libc dynamic:** +```bash +native-image --static-nolibc +``` + +## Performance and optimization + +**If you want fastest build time (dev iteration):** +```bash +native-image -Ob +``` + +**If you want best runtime performance:** +```bash +native-image -O3 # or combine with --pgo +``` + +**If you want to optimize for binary size:** +```bash +native-image -Os +``` + +**If you want to collect PGO profile data:** +```bash +native-image --pgo-instrument +./myapp # run to collect profile +native-image --pgo=default.iprof +``` + +**If you want to change the garbage collector:** +```bash +native-image --gc=G1 # G1 (GraalVM EE only) +native-image --gc=epsilon # no GC (throughput) +native-image --gc=serial # default +``` + +**If you want to target the current machine's CPU features:** +```bash +native-image -march=native +``` + +**If you need maximum compatibility across machines:** +```bash +native-image -march=compatibility +``` + +**If you want to limit build parallelism:** +```bash +native-image --parallelism=4 +``` + +## Debugging and diagnostics + +**If you want debug symbols in the binary:** +```bash +native-image -g +``` + +**If you want verbose build output:** +```bash +native-image --verbose +``` + +**If you want to inspect class initialization and substitutions:** +```bash +native-image --diagnostics-mode +``` + +**If you want a detailed HTML build report:** +```bash +native-image --emit build-report +# or: --emit build-report=report.html +``` + +**If you want to trace instantiation of a specific class:** +```bash +native-image --trace-object-instantiation=com.example.MyClass +``` + +## Network support + +**If the binary needs HTTP/HTTPS:** +```bash +native-image --enable-http --enable-https +``` + +**If the binary needs specific URL protocols:** +```bash +native-image --enable-url-protocols=http,https +``` + +## Monitoring and observability + +**If you need runtime monitoring (heap dumps, JFR, thread dumps):** +```bash +native-image --enable-monitoring=heapdump,jfr,threaddump +``` + +## Security and compliance + +**If you need all security services (e.g. TLS/SSL):** +```bash +native-image --enable-all-security-services +``` + +**If you need a Software Bill of Materials (SBOM):** +```bash +native-image --enable-sbom=embed,export +``` + +## Cross-compilation and platform + +**If you need to cross-compile for a different OS/arch:** +```bash +native-image --target=linux-aarch64 +``` + +**If you need a custom C compiler:** +```bash +native-image --native-compiler-path=/usr/bin/gcc +``` + +## Info and discovery + +**If you want to list available CPU features:** +```bash +native-image --list-cpu-features +``` + +**If you want to list observable modules:** +```bash +native-image --list-modules +``` + +**If you want to see the native toolchain and build settings:** +```bash +native-image --native-image-info +``` diff --git a/substratevm/skills/building-native-image/references/reachability-metadata.md b/substratevm/skills/building-native-image/references/reachability-metadata.md new file mode 100644 index 000000000000..ead39d49b6d0 --- /dev/null +++ b/substratevm/skills/building-native-image/references/reachability-metadata.md @@ -0,0 +1,409 @@ +# Reachability Metadata GraalVM Native Image + +## Table of Contents + +1. [Diagnosing the Error Type](#1-diagnosing-the-error-type) +2. [Where to Put Metadata Files](#2-where-to-put-metadata-files) +3. [Reflection Metadata](#3-reflection-metadata) +4. [JNI Metadata](#4-jni-metadata) +5. [Resource Metadata](#5-resource-metadata) +6. [Serialization Metadata](#6-serialization-metadata) +7. [Conditional Metadata Entries](#7-conditional-metadata-entries) +8. [Debugging Tips](#8-debugging-tips) +9. [Full Sample reachability-metadata.json](#9-full-sample-reachability-metadatajson) + + +## 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](#4-reflection-metadata) - register the type | +| `MissingReflectionRegistrationError` | Reflective access to unregistered class/method/field | [Reflection Metadata](#4-reflection-metadata) | +| `NoSuchMethodException` | Method not registered for reflective invocation | [Reflection Metadata - Methods](#methods) | +| `NoSuchFieldException` | Field not registered for reflective access | [Reflection Metadata - Fields](#fields) | +| `MissingJNIRegistrationError` | JNI lookup of unregistered type/member | [JNI Metadata](#5-jni-metadata) | +| `MissingForeignRegistrationError` | FFM downcall/upcall without registered descriptor | Foreign section (advanced, see GraalVM docs) | +| `MissingResourceException` | Resource bundle not included | [Resource Metadata - Bundles](#resource-bundles) | + + +**Quick diagnostic command** - run the app with warning mode to see all missing registrations without crashing: +```shell +java -XX:MissingRegistrationReportingMode=Warn -jar your-app.jar +``` +Use `Exit` mode during testing to catch errors hidden inside `catch (Throwable t)` blocks: +```shell +java -XX:MissingRegistrationReportingMode=Exit -jar your-app.jar +``` +Enable strict metadata mode at build time: +```shell +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/ + └── / + └── / + └── reachability-metadata.json +``` + +The file contains a top-level object with one key per metadata type: +```json +{ + "reflection": [], + "resources": [] +} +``` + +> **Alternative approaches (when JSON isn't enough):** +> - Pass constant arguments to `Class.forName("Foo")`, `getMethod(...)`, etc. - native-image evaluates these at build time automatically. +> - Use `-H:Preserve=` to preserve entire packages. + +--- + +## 3. Reflection Metadata + +### Register a Type (fixes `NoClassDefFoundError`, `MissingReflectionRegistrationError`) + +```json +{ + "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:** +```json +{ + "type": "com.example.MyClass", + "methods": [ + { "name": "myMethod", "parameterTypes": ["java.lang.String", "int"] }, + { "name": "", "parameterTypes": [] } + ] +} +``` +> Use `""` for constructors. + +**Register all methods (less precise, larger binary):** +```json +{ + "type": "com.example.MyClass", + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allPublicConstructors": true +} +``` +- `allDeclared*` - methods/constructors declared directly on this type +- `allPublic*` - all public methods/constructors including those inherited from supertypes + +### Fields + +Fixes `NoSuchFieldException` and `MissingReflectionRegistrationError` on `Field.get()` / `Field.set()`. + +**Register specific fields:** +```json +{ + "type": "com.example.MyClass", + "fields": [ + { "name": "myField" }, + { "name": "anotherField" } + ] +} +``` + +**Register all fields:** +```json +{ + "type": "com.example.MyClass", + "allDeclaredFields": true, + "allPublicFields": true +} +``` + +### Dynamic Proxies + +For classes obtained via `Proxy.newProxyInstance(...)` - the type is the proxy's interface list: +```json +{ + "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)`: +```json +{ + "type": "com.example.MyClass", + "unsafeAllocated": true +} +``` + +### Full Type Entry Reference + +```json +{ + "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-metadata` with `-XX:MissingRegistrationReportingMode=Warn` to see what's missing. + +**Register a JNI-accessible type:** +```json +{ + "reflection": [ + { + "type": "com.example.MyClass", + "jniAccessible": true + } + ] +} +``` + +**Add fields and methods for JNI access:** +```json +{ + "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: + +```json +{ + "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:** +```json +{ "glob": "config/app.properties" } // exact file +{ "glob": "**/**.json" } // all JSON files anywhere +{ "glob": "static/images/*.png" } // all PNGs in one directory +``` + +> **Note:** `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 + +```json +{ + "resources": [ + { + "module": "library.module", + "glob": "resource-file.txt" + } + ] +} +``` + +### Resource Bundles + +Fixes `MissingResourceException` from `ResourceBundle.getBundle(...)`. + +```json +{ + "resources": [ + { "bundle": "com.example.Messages" }, + { "bundle": "com.example.Errors" } + ] +} +``` + +With a specific module: +```json +{ + "resources": [ + { "module": "app.module", "bundle": "com.example.Messages" } + ] +} +``` + +Bundles are included for all locales embedded in the image. To control locales: +```shell +native-image -Duser.country=US -Duser.language=en -H:IncludeLocales=fr,de +# or include everything: +native-image -H:+IncludeAllLocales +``` + +--- + +## 6. Serialization Metadata + +Fixes `InvalidClassException`, serialization `StreamCorruptedException`, or `ClassNotFoundException` during `ObjectInputStream.readObject()`. + +### In JSON + +```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: +```java +var filter = ObjectInputFilter.Config.createFilter("com.example.MyClass;!*;"); +objectInputStream.setObjectInputFilter(filter); +``` + +### Proxy Serialization + +```json +{ + "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. + +```json +{ + "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. + +--- + +## 9. Full Sample reachability-metadata.json + +```json +{ + "reflection": [ + { + "condition": { "typeReached": "com.example.App" }, + "type": "com.example.MyClass", + "fields": [ + { "name": "myField" } + ], + "methods": [ + { "name": "myMethod", "parameterTypes": ["java.lang.String"] }, + { "name": "", "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" + } + ] +} +``` \ No newline at end of file