graalvm-native-image

安装量: 91
排名: #8828

安装

npx skills add https://github.com/giuseppe-trisciuoglio/developer-kit --skill graalvm-native-image

GraalVM Native Image for Java Applications Expert skill for building high-performance native executables from Java applications using GraalVM Native Image, dramatically reducing startup time and memory consumption. Overview GraalVM Native Image compiles Java applications ahead-of-time (AOT) into standalone native executables. These executables start in milliseconds, require significantly less memory than JVM-based deployments, and are ideal for serverless functions, CLI tools, and microservices where fast startup and low resource usage are critical. This skill provides a structured workflow to migrate JVM applications to native binaries, covering build tool configuration, framework-specific patterns, reflection metadata management, and an iterative approach to resolving native build failures. When to Use Use this skill when: Converting a JVM-based Java application to a GraalVM native executable Optimizing cold start times for serverless or containerized deployments Reducing memory footprint (RSS) of Java microservices Configuring Maven or Gradle with GraalVM Native Build Tools Resolving ClassNotFoundException , NoSuchMethodException , or missing resource errors in native builds Generating or editing reflect-config.json , resource-config.json , or other GraalVM metadata files Using the GraalVM tracing agent to collect reachability metadata Implementing RuntimeHints for Spring Boot native support Building native images with Quarkus or Micronaut Instructions 1. Contextual Project Analysis Before any configuration, analyze the project to determine the build tool, framework, and dependencies: Detect the build tool:

Check for Maven

if [ -f "pom.xml" ] ; then echo "Build tool: Maven"

Check for Maven wrapper

[ -f "mvnw" ] && echo "Maven wrapper available" fi

Check for Gradle

if
[
-f
"build.gradle"
]
||
[
-f
"build.gradle.kts"
]
;
then
echo
"Build tool: Gradle"
[
-f
"build.gradle.kts"
]
&&
echo
"Kotlin DSL"
[
-f
"gradlew"
]
&&
echo
"Gradle wrapper available"
fi
Detect the framework by analyzing dependencies:
Spring Boot
Look for
spring-boot-starter-*
in
pom.xml
or
build.gradle
Quarkus
Look for
quarkus-*
dependencies
Micronaut
Look for
micronaut-*
dependencies
Plain Java
No framework dependencies detected Check the Java version: java -version 2

&1

GraalVM Native Image requires Java 17+ (recommended: Java 21+)

Identify potential native image challenges:
Reflection-heavy libraries (Jackson, Hibernate, JAXB)
Dynamic proxy usage (JDK proxies, CGLIB)
Resource bundles and classpath resources
JNI or native library dependencies
Serialization requirements
2. Build Tool Configuration
Configure the appropriate build tool plugin based on the detected environment.
For Maven projects
, add a dedicated
native
profile to keep the standard build clean. See the
Maven Native Profile Reference
for full configuration.
Key Maven setup:
<
profiles
>
<
profile
>
<
id
>
native
</
id
>
<
build
>
<
plugins
>
<
plugin
>
<
groupId
>
org.graalvm.buildtools
</
groupId
>
<
artifactId
>
native-maven-plugin
</
artifactId
>
<
version
>
0.10.6
</
version
>
<
extensions
>
true
</
extensions
>
<
executions
>
<
execution
>
<
id
>
build-native
</
id
>
<
goals
>
<
goal
>
compile-no-fork
</
goal
>
</
goals
>
<
phase
>
package
</
phase
>
</
execution
>
</
executions
>
<
configuration
>
<
imageName
>
${project.artifactId}
</
imageName
>
<
buildArgs
>
<
buildArg
>
--no-fallback
</
buildArg
>
</
buildArgs
>
</
configuration
>
</
plugin
>
</
plugins
>
</
build
>
</
profile
>
</
profiles
>
Build with:
./mvnw -Pnative package
For Gradle projects
, apply the
org.graalvm.buildtools.native
plugin. See the
Gradle Native Plugin Reference
for full configuration.
Key Gradle setup (Kotlin DSL):
plugins
{
id
(
"org.graalvm.buildtools.native"
)
version
"0.10.6"
}
graalvmNative
{
binaries
{
named
(
"main"
)
{
imageName
.
set
(
project
.
name
)
buildArgs
.
add
(
"--no-fallback"
)
}
}
}
Build with:
./gradlew nativeCompile
3. Framework-Specific Configuration
Each framework has its own AOT strategy. Apply the correct configuration based on the detected framework.
Spring Boot
(3.x+): Spring Boot has built-in GraalVM support with AOT processing. See the
Spring Boot Native Reference
for patterns including
RuntimeHints
,
@RegisterReflectionForBinding
, and test support.
Key points:
Use
spring-boot-starter-parent
3.x+ which includes the native profile
Register reflection hints via
RuntimeHintsRegistrar
Run AOT processing with
process-aot
goal
Build with:
./mvnw -Pnative native:compile
or
./gradlew nativeCompile
Quarkus and Micronaut
These frameworks are designed native-first and require minimal additional configuration. See the Quarkus & Micronaut Reference . 4. GraalVM Reachability Metadata Native Image uses a closed-world assumption — all code paths must be known at build time. Dynamic features like reflection, resources, and proxies require explicit metadata configuration. Metadata files are placed in META-INF/native-image/// : File Purpose reachability-metadata.json Unified metadata (reflection, resources, JNI, proxies, bundles, serialization) reflect-config.json Legacy: Reflection registration resource-config.json Legacy: Resource inclusion patterns proxy-config.json Legacy: Dynamic proxy interfaces serialization-config.json Legacy: Serialization registration jni-config.json Legacy: JNI access registration See the Reflection & Resource Config Reference for complete format and examples. 5. The Iterative Fix Engine Native image builds often fail due to missing metadata. Follow this iterative approach: Step 1 — Execute the native build:

Maven

./mvnw -Pnative package 2

&1 | tee native-build.log

Gradle

./gradlew nativeCompile 2

&1 | tee native-build.log Step 2 — Parse build errors and identify the root cause: Common error patterns and their fixes: Error Pattern Cause Fix ClassNotFoundException: com.example.MyClass Missing reflection metadata Add to reflect-config.json or use @RegisterReflectionForBinding NoSuchMethodException Method not registered for reflection Add method to reflection config MissingResourceException Resource not included in native image Add to resource-config.json Proxy class not found Dynamic proxy not registered Add interface list to proxy-config.json UnsupportedFeatureException: Serialization Missing serialization metadata Add to serialization-config.json Step 3 — Apply fixes by updating the appropriate metadata file or using framework annotations. Step 4 — Rebuild and verify. Repeat until the build succeeds. Step 5 — If manual fixes are insufficient , use the GraalVM tracing agent to collect reachability metadata automatically. See the Tracing Agent Reference . 6. Validation and Benchmarking Once the native build succeeds: Verify the executable runs correctly:

Run the native executable

./target/ < app-name

For Spring Boot, verify the application context loads

curl http://localhost:8080/actuator/health Measure startup time:

Time the startup

time ./target/ < app-name

For Spring Boot, check the startup log

./target/ < app-name

2

&1 | grep "Started .* in" Measure memory footprint (RSS):

On Linux

ps -o rss,vsz,comm -p $( pgrep < app-name

)

On macOS

ps -o rss,vsz,comm -p $( pgrep < app-name

) Compare with JVM baseline: Metric JVM Native Improvement Startup time ~2-5s ~50-200ms 10-100x Memory (RSS) ~200-500MB ~30-80MB 3-10x Binary size JRE + JARs Single binary Simplified 7. Docker Integration Build minimal container images with native executables:

Multi-stage build

FROM ghcr.io/graalvm/native-image-community:21 AS builder WORKDIR /app COPY . . RUN ./mvnw -Pnative package -DskipTests

Minimal runtime image

FROM debian:bookworm-slim COPY --from = builder /app/target/ /app/ EXPOSE 8080 ENTRYPOINT [ "/app/" ] For Spring Boot applications, use paketobuildpacks/builder-jammy-tiny with Cloud Native Buildpacks: ./mvnw -Pnative spring-boot:build-image Best Practices Start with the tracing agent on complex projects to generate an initial metadata baseline Use the native profile to keep native-specific config separate from standard builds Prefer --no-fallback to ensure a true native build (no JVM fallback) Test with nativeTest to run JUnit tests in native mode Use GraalVM Reachability Metadata Repository for third-party library metadata Minimize reflection — prefer constructor injection and compile-time DI where possible Include resource patterns explicitly rather than relying on classpath scanning Profile before and after — always measure startup and memory improvements Use Java 21+ for the best GraalVM compatibility and performance Keep GraalVM and Native Build Tools versions aligned Examples Example 1: Adding Native Support to a Spring Boot Maven Project Scenario: You have a Spring Boot 3.x REST API and want to compile it to a native executable. Step 1 — Add the native profile to pom.xml : < profiles

< profile

< id

native </ id

< build

< plugins

< plugin

< groupId

org.springframework.boot </ groupId

< artifactId

spring-boot-maven-plugin </ artifactId

< executions

< execution

< id

process-aot </ id

< goals

< goal

process-aot </ goal

</ goals

</ execution

</ executions

</ plugin

< plugin

< groupId

org.graalvm.buildtools </ groupId

< artifactId

native-maven-plugin </ artifactId

</ plugin

</ plugins

</ build

</ profile

</ profiles

Step 2 — Register reflection hints for DTOs: @RestController @RegisterReflectionForBinding ( { UserDto . class , OrderDto . class } ) public class UserController { @GetMapping ( "/users/{id}" ) public UserDto getUser ( @PathVariable Long id ) { return userService . findById ( id ) ; } } Step 3 — Build and run: ./mvnw -Pnative native:compile ./target/myapp

Started MyApplication in 0.089 seconds

Example 2: Resolving a Reflection Error in Native Build Scenario: Native build fails with ClassNotFoundException for a Jackson-serialized DTO. Error output: com.oracle.svm.core.jdk.UnsupportedFeatureError: Reflection registration missing for class com.example.dto.PaymentResponse Fix — Add to src/main/resources/META-INF/native-image/reachability-metadata.json : { "reflection" : [ { "type" : "com.example.dto.PaymentResponse" , "allDeclaredConstructors" : true , "allDeclaredMethods" : true , "allDeclaredFields" : true } ] } Or use the Spring Boot annotation approach: @RegisterReflectionForBinding ( PaymentResponse . class ) @Service public class PaymentService { / ... / } Example 3: Using the Tracing Agent for a Complex Project Scenario: A project with many third-party libraries needs comprehensive reachability metadata.

1. Build the JAR

./mvnw package -DskipTests

2. Run with the tracing agent

java -agentlib:native-image-agent = config-output-dir = src/main/resources/META-INF/native-image \ -jar target/myapp.jar

3. Exercise all endpoints

curl http://localhost:8080/api/users curl -X POST http://localhost:8080/api/orders -H 'Content-Type: application/json' -d '{"item":"test"}' curl http://localhost:8080/actuator/health

4. Stop the application (Ctrl+C), then build native

./mvnw -Pnative native:compile

5. Verify

./target/myapp
Constraints and Warnings
Critical Constraints
GraalVM Native Image requires Java 17+
(Java 21+ recommended for best compatibility)
Closed-world assumption
All code paths must be known at build time — dynamic class loading, runtime bytecode generation, and
MethodHandles.Lookup
may not work
Build time and memory
Native compilation is resource-intensive — expect 2-10 minutes and 4-8 GB RAM for typical projects
Not all libraries are compatible
Libraries relying heavily on reflection, dynamic proxies, or CGLIB may require extensive metadata configuration
AOT profiles are fixed at build time
Spring Boot
@Profile
and
@ConditionalOnProperty
are evaluated during AOT processing, not at runtime
Common Pitfalls
Forgetting
--no-fallback
Without this flag, the build may silently produce a JVM fallback image instead of a true native executable
Incomplete tracing agent coverage
The agent only captures code paths exercised during the run — ensure all features are tested
Version mismatches
Keep GraalVM JDK, Native Build Tools plugin, and framework versions aligned to avoid incompatibilities
Classpath differences
The classpath at AOT/build time must match runtime — adding/removing JARs after native compilation causes failures Security Considerations Native executables are harder to decompile than JARs, but are not tamper-proof Ensure secrets are not embedded in the native image at build time Use environment variables or external config for sensitive data Troubleshooting Issue Solution Build runs out of memory Increase build memory: -J-Xmx8g in buildArgs Build takes too long Use build cache, reduce classpath, enable quick build mode for dev Application crashes at runtime Missing reflection/resource metadata — run tracing agent Spring Boot context fails to load Check @Conditional beans and profile-dependent config Third-party library not compatible Check GraalVM Reachability Metadata repo or add manual hints
返回排行榜