ideabrowser.com — find trending startup ideas with real demand
Try itnpx skills add https://github.com/github/awesome-copilot --skill java-add-graalvm-native-image-supportYou are an expert in adding GraalVM native image support to Java applications. Your goal is to:
Follow Oracle's best practices for GraalVM native images and use an iterative approach to resolve issues.
pom.xml exists (Maven) or build.gradle/build.gradle.kts exists (Gradle)spring-boot-starter dependenciesquarkus- dependenciesmicronaut- dependenciesAdd the GraalVM Native Build Tools plugin within a native profile in pom.xml:
<profiles>
<profile>
<id>native</id>
<build>
<plugins>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<version>[latest-version]</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>
<mainClass>${main.class}</mainClass>
<buildArgs>
<buildArg>--no-fallback</buildArg>
</buildArgs>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
For Spring Boot projects, ensure the Spring Boot Maven plugin is in the main build section:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Add the GraalVM Native Build Tools plugin to build.gradle:
plugins {
id 'org.graalvm.buildtools.native' version '[latest-version]'
}
graalvmNative {
binaries {
main {
imageName = project.name
mainClass = application.mainClass.get()
buildArgs.add('--no-fallback')
}
}
}
Or for Kotlin DSL (build.gradle.kts):
plugins {
id("org.graalvm.buildtools.native") version "[latest-version]"
}
graalvmNative {
binaries {
named("main") {
imageName.set(project.name)
mainClass.set(application.mainClass.get())
buildArgs.add("--no-fallback")
}
}
}
Run the appropriate build command:
Maven:
mvn -Pnative native:compile
Gradle:
./gradlew nativeCompile
Spring Boot (Maven):
mvn -Pnative spring-boot:build-image
Quarkus (Maven):
./mvnw package -Pnative
Micronaut (Maven):
./mvnw package -Dpackaging=native-image
Common issues and solutions:
If you see errors about missing reflection configuration, create or update src/main/resources/META-INF/native-image/reflect-config.json:
[
{
"name": "com.example.YourClass",
"allDeclaredConstructors": true,
"allDeclaredMethods": true,
"allDeclaredFields": true
}
]
For missing resources, create src/main/resources/META-INF/native-image/resource-config.json:
{
"resources": {
"includes": [
{"pattern": "application.properties"},
{"pattern": ".*\\.yml"},
{"pattern": ".*\\.yaml"}
]
}
}
For JNI-related errors, create src/main/resources/META-INF/native-image/jni-config.json:
[
{
"name": "com.example.NativeClass",
"methods": [
{"name": "nativeMethod", "parameterTypes": ["java.lang.String"]}
]
}
]
For dynamic proxy errors, create src/main/resources/META-INF/native-image/proxy-config.json:
[
["com.example.Interface1", "com.example.Interface2"]
]
java -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image -jar target/app.jar
Once built successfully:
When to Add Custom RuntimeHints:
Create a RuntimeHintsRegistrar implementation only if you need to register custom hints:
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
public class MyRuntimeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
// Register reflection hints
hints.reflection().registerType(
MyClass.class,
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
MemberCategory.INVOKE_DECLARED_METHODS)
);
// Register resource hints
hints.resources().registerPattern("custom-config/*.properties");
// Register serialization hints
hints.serialization().registerType(MySerializableClass.class);
}
}
Register it in your main application class:
@SpringBootApplication
@ImportRuntimeHints(MyRuntimeHints.class)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Common Spring Boot Native Image Issues:
Logback Configuration: Add to application.properties:
# Disable Logback's shutdown hook in native images
logging.register-shutdown-hook=false
If using custom Logback configuration, ensure logback-spring.xml is in resources and add to RuntimeHints:
hints.resources().registerPattern("logback-spring.xml");
hints.resources().registerPattern("org/springframework/boot/logging/logback/*.xml");
Jackson Serialization: For custom Jackson modules or types, register them:
hints.serialization().registerType(MyDto.class);
hints.reflection().registerType(
MyDto.class,
hint -> hint.withMembers(
MemberCategory.DECLARED_FIELDS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS
)
);
Add Jackson mix-ins to reflection hints if used:
hints.reflection().registerType(MyMixIn.class);
Jackson Modules: Ensure Jackson modules are on the classpath:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
@RegisterForReflection annotation for reflection needsCommon Quarkus Native Image Tips:
Reflection Registration: Use annotations instead of manual configuration:
@RegisterForReflection(targets = {MyClass.class, MyDto.class})
public class ReflectionConfiguration {
}
Or register entire packages:
@RegisterForReflection(classNames = {"com.example.package.*"})
Resource Inclusion: Add to application.properties:
quarkus.native.resources.includes=config/*.json,templates/**
quarkus.native.additional-build-args=--initialize-at-run-time=com.example.RuntimeClass
Database Drivers: Ensure you're using Quarkus-supported JDBC extensions:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-postgresql</artifactId>
</dependency>
Build-Time vs Runtime Initialization: Control initialization with:
quarkus.native.additional-build-args=--initialize-at-build-time=com.example.BuildTimeClass
quarkus.native.additional-build-args=--initialize-at-run-time=com.example.RuntimeClass
Container Image Build: Use Quarkus container-image extensions:
quarkus.native.container-build=true
quarkus.native.builder-image=mandrel
@ReflectionConfig and @Introspected annotations as neededCommon Micronaut Native Image Tips:
Bean Introspection: Use @Introspected for POJOs to avoid reflection:
@Introspected
public class MyDto {
private String name;
private int value;
// getters and setters
}
Or enable package-wide introspection in application.yml:
micronaut:
introspection:
packages:
- com.example.dto
Reflection Configuration: Use declarative annotations:
@ReflectionConfig(
type = MyClass.class,
accessType = ReflectionConfig.AccessType.ALL_DECLARED_CONSTRUCTORS
)
public class MyConfiguration {
}
Resource Configuration: Add resources to native image:
@ResourceConfig(
includes = {"application.yml", "logback.xml"}
)
public class ResourceConfiguration {
}
Native Image Configuration: In build.gradle:
graalvmNative {
binaries {
main {
buildArgs.add("--initialize-at-build-time=io.micronaut")
buildArgs.add("--initialize-at-run-time=io.netty")
buildArgs.add("--report-unsupported-elements-at-runtime")
}
}
}
HTTP Client Configuration: For Micronaut HTTP clients, ensure netty is properly configured:
micronaut:
http:
client:
read-timeout: 30s
netty:
default:
allocator:
max-order: 3
--no-fallback to catch all native image issuesresource-config.json--gc=serial (default) or --gc=epsilon (no-op GC for testing) and analyze dependencies