GraalVM's native image functionality allows you to transform Java applications into self-contained executables. This offers advantages like faster startup times and reduced memory footprint. However, applications relying on dynamic features like reflection, JNI, or dynamic class loading can be tricky to configure for native image generation.
This article explores how the native-image-agent
simplifies this process by automatically gathering metadata about your application's dynamic behavior.
Understanding the Challenge
The core principle behind native images is static analysis. The native-image
tool needs to know all classes and resources your application uses at build time. This becomes a challenge when your code utilizes reflection or other dynamic features that determine classes or resources at runtime.
Traditionally, you would need to manually provide configuration files to the native-image
tool, specifying the classes, methods, and resources required for your application to function correctly. This can be a tedious and error-prone process.
The native-image-agent
to the Rescue
GraalVM's native-image-agent
acts as a helping hand by automating metadata collection. Here's how it works:
-
Running the Agent:
- Ensure you have a GraalVM JDK installed.
- Include the agent in your application's launch command using the
-agentlib
option:
java -agentlib:native-image-agent=config-output-dir=config-dir[,options] -jar your-application.jar
- Replace
config-dir
with the desired directory to store the generated configuration files (JSON format). - You can optionally specify additional agent options (comma-separated) after the directory path.
-
Automatic Metadata Collection:
-
Run your application with the agent enabled. During execution, the agent tracks how your application uses dynamic features like reflection and JNI.
-
This information is then used to generate corresponding JSON configuration files in the specified directory.
These files typically include:
jni-config.json
(for JNI usage)proxy-config.json
(for dynamic proxy objects)reflect-config.json
(for reflection usage)resource-config.json
(for classpath resources)
-
-
Building the Native Image:
- Place the generated JSON configuration files in a directory named
META-INF/native-image
on your application's classpath. - Use the
native-image
tool to build your native image. The tool will automatically discover and use the configuration files during the build process.
- Place the generated JSON configuration files in a directory named
Putting it into Practice: An Example
Let's consider a simple application that uses reflection to reverse a string:
import java.lang.reflect.Method;
class StringReverser {
static String reverse(String input) {
return new StringBuilder(input).reverse().toString();
}
}
public class ReflectionExample {
public static void main(String[] args) throws ReflectiveOperationException {
if (args.length == 0) {
System.err.println("Please provide a string to reverse");
return;
}
String input = args[0];
Class<?> clazz = Class.forName(StringReverser.class.getName());
Method method = clazz.getDeclaredMethod("reverse", String.class);
String result = (String) method.invoke(null, input);
System.out.println("Reversed String: " + result);
}
}
-
Run the application with the agent, specifying a directory to store the generated configuration files (e.g.,
config
):java -agentlib:native-image-agent=config-output-dir=config ReflectionExample "Hello World"
-
After running the application, you'll find a
reflect-config.json
file in theconfig
directory. This file contains information about the reflection usage in your application. -
Copy the content of the config directory generated from step 1 to a directory named
META-INF/native-image
within your project's root directory. -
Use the
native-image
tool to build the native image, referencing your application class:native-image ReflectionExample
This command will leverage the reflect-config.json
to correctly configure the native image build process for reflection.
Conclusion
The native-image-agent
is a valuable tool for streamlining the creation of native images from Java applications that rely on dynamic features. By automating metadata collection, it simplifies the configuration process and reduces the risk of errors. This allows you to enjoy the benefits of native images with less hassle.
Leave a Reply