Tracing Agent
When building native images, the hard part is how to find out the places where manual configurations are required. This includes the usage of Reflection API, dynamic proxies, and resources.
Basic Usage
GraalVM provides an agent to run with normal Java programs. This agent tracks all dynamic usages that require manual configurations. The agent creates configuration files based on the usages. These configuration files can be used directly with native-image
.
Tracing agent is enabled using the -agentlib
option of java
command when running the Java app. Name of the tracing agent is native-image-agent
. There are several options that can be passed to the agent. These options are passed as a comma separated string.
Option | Description |
---|---|
config-output-dir | Output directory of generated configuration files |
config-merge-dir | Directory of an existing set of configuration files to merge configurations |
config-write-period-secs | Periodically write configuration files |
config-write-initial-delay-secs | Initial delay to write configuration files |
config-to-omit | Directory of configuration files to omit |
experimental-omit-config-from-classpath | Omit configuration files from classpath |
no-builtin-caller-filter | Disable built-in caller filter |
builtin-caller-filter | Enable/Disable built-in caller filter |
no-builtin-heuristic-filter | Disable built-in heuristic filter |
builtin-heuristic-filter | Enable/Disable built-in heuristic filter |
caller-filter-file | Caller filter |
access-filter-file | Access filter |
experimental-class-loader-support | Class loader support |
experimental-class-define-support | Class define support |
build | Build native image |
experimental-configuration-with-origins | Configuration files with origins |
track-reflection-metadata | Track reflection metadata |
trace-output | Output directory of trace files |
Tracing agent library is included in GraalVM. If JDK in GraalVM is used to run the Java app, then using native-image-agent
as the library name is enough. If using other JDK distributions, then using the full path of native-image-agent
library is required. The native library file can be found in the lib
directory of GraalVM installation.
Let's use the NonConstantReflectionExample
in Reflection as an example. Use the command below to run the example.
java -agentlib:native-image-agent=config-output-dir=./config-output \
io.vividcode.graalvm.reflection.NonConstantReflectionExample
Generated configuration files are saved in the config-output
directory. This directory contains 6 JSON files.
config-output
├── jni-config.json
├── predefined-classes-config.json
├── proxy-config.json
├── reflect-config.json
├── resource-config.json
└── serialization-config.json
Below is the content of reflect-config.json
. The toUpperCase
method of java.lang.String
is included.
[
{
"name":"java.lang.String",
"methods":[{"name":"toUpperCase","parameterTypes":[] }]}
]
Build Configuration
Configuration files generated by tracing agent can be used by native-image
. These files need to be packaged with the application's JAR file (see Build Configuration).
In the command below, configuration files are generated into src/main/resources/META-INF/native-image/io.vividcode.graalvm/reflection
directory. This is the recommended directory to place native-image
configuration files.
java -agentlib:native-image-agent=config-output-dir=./src/main/resources/META-INF/native-image/io.vividcode.graalvm/reflection \
-cp target/classes \
io.vividcode.graalvm.reflection.NonConstantReflectionExample
With configuration files embedded in the JAR file, the command to run native-image
can be simplified.
native-image -jar reflection-1.0.0-SNAPSHOT.jar reflection-example
It's possible that the agent cannot find out all the usages, because some code paths are not executed. If the app has integration tests, the tracing agent can be enabled when running the tests.
Advanced Usage
Filters
The tracing agent can filter dynamic accesses that should be exclude in the configuration. The tracing agent has built-in rules to ignore certain accesses. For example, method calls originated from JVM and some Java standard libraries are excluded.
Filter File
A filter file describes the rules to include or exclude classes. There are three types of patterns:
- Exact fully qualified class name
- A
.*
ending matches all classes in a package and that package only. - A
.**
ending matches all classes in the package and all subpackages.
Below is an example of filter config file. A filter rule can have only includeClasses
or excludeClasses
, but not both.
{ "rules": [
{"excludeClasses": "com.oracle.svm.**"},
{"includeClasses": "com.oracle.svm.tutorial.*"},
{"excludeClasses": "com.oracle.svm.tutorial.HostedHelper"}
]
}
Refer to the JSON schema of filter config.
Caller-based Filters
Caller-based filters identify the Java method performing the access. If a method's declaring class matches against a filter rule, this method is included or excluded. Caller-based filters are enabled using the caller-filter-file
option.
Access Filters
Access filters identify the targets of access. Access filters are enabled using the access-filter-file
option.
Trace Files
The tracing agent can write a trace file that contains each individual access. This mode is enabled with the trace-output
option. This option cannot be used with config-output-dir
or config-merge-dir
.