Skip to main content

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.

OptionDescription
config-output-dirOutput directory of generated configuration files
config-merge-dirDirectory of an existing set of configuration files to merge configurations
config-write-period-secsPeriodically write configuration files
config-write-initial-delay-secsInitial delay to write configuration files
config-to-omitDirectory of configuration files to omit
experimental-omit-config-from-classpathOmit configuration files from classpath
no-builtin-caller-filterDisable built-in caller filter
builtin-caller-filterEnable/Disable built-in caller filter
no-builtin-heuristic-filterDisable built-in heuristic filter
builtin-heuristic-filterEnable/Disable built-in heuristic filter
caller-filter-fileCaller filter
access-filter-fileAccess filter
experimental-class-loader-supportClass loader support
experimental-class-define-supportClass define support
buildBuild native image
experimental-configuration-with-originsConfiguration files with origins
track-reflection-metadataTrack reflection metadata
trace-outputOutput directory of trace files
Path of agent library

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"}
]
}
info

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.