Automatically configure native image reflection configuration

Published: 2019-12-01, Updated: 2020-05-11

A Context about GraalVM Native Image reflection support

When you use reflection on your project and compiles it to a native-image binary you could have issues while running this executable cause it has some limitations on reflection. Basicaly everything that is not explicitly referenced at the code will be removed by native-image at compiling time and won't be available at runtime.

Native Image's solution

Native image gives you some options to bypass this problem

  1. Don't use reflection
  2. NativeImage will try to automatically detect whether the class, method, field, etc. will be used by reflection at runtime and won't remove the component (ref 1)
  3. You can manually configure a class and it's components to prevent them to be removed at compile time (ref 2). It is necessary because auto detection is powerfull but it have caveats, when you have a very complex reflection process like Hibernate or Jackson Mapper do, it will be very hard to native-image automatically detects it.

Let'ts make it easier to configure your reflections

If you use Jackson for example there is no exit, you will have to manually configure your classes for reflection support.

Problem is: it is very hard to have to configure every class at the reflect.json every time you create one, also, the chance of you forget to do such configuration is too high, in the end your software will work in java version but not in binary, that's not good.

Let me present Graal Reflection Configuration Generator to you, using it you won't have to create JSON files and configure every class, you can annotate the class which you want to be available for reflection, you can also configure a entire package to be scanned for you. No additonal configuration, when you compile your program GRCG will automatically make all the necessary configuration for you.

What GRCG does in the background?

Using annotation processors GRCG scan for annotated classes or packages, generate a reflect.json and attach it at the jar resources, this way native-image will be able to register these classes and everything will work when you run your compiled program.

How to install it?

Just configure GRCG in your dependencies, you just need it at compile time, then it won't make your program bigger.

Configuring on gradle

dependencies {
  compileOnly("com.mageddo.nativeimage:reflection-config-generator:2.3.4")
  annotationProcessor("com.mageddo.nativeimage:reflection-config-generator:2.3.4")
}

Configuring on maven

<dependencies>
  <dependency>
    <groupId>com.mageddo.nativeimage</groupId>
    <artifactId>reflection-config-generator</artifactId>
    <version>2.3.4</version>
    <scope>provided</scope>
  </dependency>
</dependencies>

Configuring on vanilla java

javac -cp reflection-config-generator.jar Main.java

Creating a config class

@Reflection(declaredConstructors = true, declaredFields = true, scanPackage = "com.github.vo")
public class Config {}

This way it will scan all com.github.vo package classes. See see working samples for more details


Sonatype Commands Avro Bookmarks

Comments