jadechenfei / graalvm-hint

Generates GraalVM configuration hints for native-image applications.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

GraalVM Hint Processor

GraalVM Enabled GitHub Action Coverage Maintainability Rating Lines of Code

GraalVM Hint Processor helps generate GraalVM hints for building native-image applications.

Fully AOT processing library, no dependencies, no runtime side-affects.

Features:

Dependency 🚀

Java 11+ is supported.

Gradle

annotationProcessor "io.goodforgod:graalvm-hint-processor:0.18.1"
compilyOnly "io.goodforgod:graalvm-hint-annotations:0.18.1"

Maven

<dependency>
    <dependency>
        <groupId>io.goodforgod</groupId>
        <artifactId>graalvm-hint-annotations</artifactId>
        <version>0.18.1</version>
        <scope>compile</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>io.goodforgod</groupId>
        <artifactId>graalvm-hint-processor</artifactId>
        <version>0.18.1</version>
        <scope>provided</scope>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.10.0</version>
            <configuration>
                <annotationProcessorPaths>
                    <path>
                        <groupId>io.goodforgod</groupId>
                        <artifactId>graalvm-hint-processor</artifactId>
                        <version>0.18.1</version>
                    </path>
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>

ReflectionHint

You can read more about GraalVM reflection configuration in official documentation here.

There are available access hints:

  • allPublicFields
  • allPublicMethods
  • allPublicConstructors
  • allDeclaredFields
  • allDeclaredMethods
  • allDeclaredConstructors

Generating reflection access, most used cases is DTOs that are used for serialization/deserialization in any format (JSON for example).

Self Configuration

Simple case for single Java class:

@ReflectionHint
public class RequestOnly {

    private String name;
}

Generated reflection-config.json:

[{
  "name": "io.goodforgod.graalvm.hint.processor.RequestOnly",
  "allDeclaredConstructors": true,
  "allDeclaredFields": true,
  "allDeclaredMethods": true
}]

Complex Configuration

There may be more different cases, like generating hints for classes that are package private or just private, also there hint can be used for whole package.

Complex example generating reflection access:

@ReflectionHint(types = { Response.class, Request.class }, value = ReflectionHint.AccessType.ALL_DECLARED_FIELDS)
@ReflectionHint(typeNames = { "io.goodforgod.graalvm.hint.processor"})
public class ReflectionConfig {

    private String name;
}

Generated reflection-config.json:

[{
  "name": "io.goodforgod.graalvm.hint.processor",
  "allDeclaredConstructors": true,
  "allDeclaredFields": true,
  "allDeclaredMethods": true
},
{
  "name": "io.goodforgod.example.Response",
  "allDeclaredFields": true
},
{
  "name": "io.goodforgod.example.Request",
  "allDeclaredFields": true
}]

ResourceHint

You can read more about GraalVM resource configuration in official documentation here.

Hint allows generating config for resource files to be included/excluded when building native application. You can also include bundles into native image using this Hint.

Include Patterns

Resource patterns specified with Java regexp to Include during native-image generation into the final application.

Include Hint:

@ResourceHint(include = { "simplelogger.properties", "application.yml", "*.xml" })
public class ResourceNames {

}

Generated resource-config.json:

{
  "resources": {
    "includes": [
      { "pattern" : "*.xml" },
      { "pattern": "application.yml" },
      { "pattern": "simplelogger.properties" }
    ]
  }
}

Exclude Patterns

Resource patterns specified with Java regexp to Exclude during native-image generation into the final application.

Exclude Hint:

@ResourceHint(exclude = { "*.xml" })
public class ResourceNames {

}

Generated resource-config.json:

{
  "resources": {
    "excludes": [
      { "pattern": "*.xml" }
    ]
  }
}

Include Bundles

Native Image needs ahead-of-time knowledge of the resource bundles your application needs so that it can load and store the appropriate bundles for usage in the generated binary.

Bundle Hint:

@ResourceHint(bundles = { "your.pkg.Bundle" })
public class ResourceNames {

}

Generated resource-config.json:

{
  "bundles": [
    { "name": "your.pkg.Bundle" }
  ]
}

NativeImageHint

You can read more about GraalVM native-image options in official documentation here.

Hint allows generating config for native-image options and initial application entrypoint.

Application Entrypoint

Simple hint configuration:

@NativeImageHint(entrypoint = EntrypointOnly.class)
public class EntrypointOnly {

    public static void main(String[] args) {}
}

Generated native-image.properties:

Args = -H:Class=io.goodforgod.graalvm.hint.processor.EntrypointOnly

Complex Options

Complex hint configuration with options:

@NativeImageHint(entrypoint = Entrypoint.class, name = "myapp", options = { NativeImageOptions.PRINT_INITIALIZATION, NativeImageOptions.INLINE_BEFORE_ANALYSIS })
public class Entrypoint {

    public static void main(String[] args) {}
}

Generated native-image.properties:

Args = -H:Class=io.goodforgod.graalvm.hint.processor.Entrypoint -H:Name=myapp \
       -H:+PrintClassInitialization \
       -H:+InlineBeforeAnalysis

InitializationHint

You can read more about GraalVM initialization configuration in official documentation here.

Hint allows generating config for what classes to instantiate in runtime and what classes to instantiate in compile time.

Runtime and Compile Time

Initialization hint configuration:

@InitializationHint(value = InitializationHint.InitPhase.BUILD, types = HintOptions.class)
@InitializationHint(value = InitializationHint.InitPhase.RUNTIME, typeNames = "io.goodforgod.graalvm.hint.processor")
public class EntrypointOnly {

}

Generated native-image.properties:

Args = --initialize-at-build-time=io.goodforgod.graalvm.hint.processor.HintOrigin.class \
       --initialize-at-run-time=io.goodforgod.graalvm.hint.processor

Entrypoint and Initialization

@NativeImageHint and @InitializationHint can annotate different classes, it doesn't matter.

Options and initialization hint configuration:

@NativeImageHint(entrypoint = Entrypoint.class)
@InitializationHint(value = InitializationHint.InitPhase.BUILD, types = HintOptions.class)
@InitializationHint(value = InitializationHint.InitPhase.RUNTIME, typeNames = "io.goodforgod.graalvm.hint.processor")
public class Entrypoint {

    public static void main(String[] args) {}
}

Generated native-image.properties:

Args = -H:Class=io.goodforgod.graalvm.hint.processor.Entrypoint \
       --initialize-at-build-time=io.goodforgod.graalvm.hint.processor.HintOrigin.class \
       --initialize-at-run-time=io.goodforgod.graalvm.hint.processor

Self Configuration

Simple case for single Java class:

@ReflectionHint
public class RequestOnly {

    private String name;
}

Generated reflection-config.json:

[{
  "name": "io.goodforgod.graalvm.hint.processor.RequestOnly",
  "allDeclaredConstructors": true,
  "allDeclaredFields": true,
  "allDeclaredMethods": true
}]

DynamicProxyHint

You can read more about GraalVM DynamicProxyHint configuration in official documentation here.

Resources & Files

Use can pass dynamic proxy resources (-H:DynamicProxyConfigurationResources) or files (-H:DynamicProxyConfigurationFiles) using corresponding options:

@DynamicProxyHint(resources = {"proxy-resource.json"}, files = {"proxy-file.json"})
public class Resource {

}

Generated native-image.properties:

Args = -H:DynamicProxyConfigurationFiles=proxy-file.json \
       -H:DynamicProxyConfigurationResources=proxy-resource.json

Interface Configuration

You can configure files yourself using annotations only without the need for manually creating JSON configurations.

@DynamicProxyHint(value = {
        @DynamicProxyHint.Configuration(interfaces = {OptionParser.class, HintOrigin.class}),
        @DynamicProxyHint.Configuration(interfaces = {HintOrigin.class})
})
public class Config {

}

Generated dynamic-proxy-hint-config.json:

[
  { "interfaces": [ "io.goodforgod.graalvm.hint.processor.OptionParser", "io.goodforgod.graalvm.hint.processor.HintOrigin" ] },
  { "interfaces": [ "io.goodforgod.graalvm.hint.processor.HintOrigin" ] }
]

Generated native-image.properties:

Args = -H:DynamicProxyConfigurationResources=META-INF/native-image/io.goodforgod.graalvm.hint.processor/hint/dynamic-proxy-config.json

Self Configuration

In case you need to add only one interface for DynamicProxy Hint configuration, you can annotate that interface directly:

@DynamicProxyHint
public interface Self {

}

Generated dynamic-proxy-hint-config.json:

[
  { "interfaces": [ "io.goodforgod.graalvm.hint.processor.Self" ] }
]

Generated native-image.properties:

Args = -H:DynamicProxyConfigurationResources=META-INF/native-image/io.goodforgod.graalvm.hint.processor/hint/dynamic-proxy-config.json

JniHint

You can read more about GraalVM JNI configuration in official documentation here.

There are available JNI access hints:

  • allPublicFields
  • allPublicMethods
  • allPublicConstructors
  • allDeclaredFields
  • allDeclaredMethods
  • allDeclaredConstructors

Self Configuration

Simple case for single Java class:

@JniHint
public class RequestOnly {

    private String name;
}

Generated jni-config.json:

[{
  "name": "io.goodforgod.graalvm.hint.processor.RequestOnly",
  "allDeclaredConstructors": true,
  "allDeclaredFields": true,
  "allDeclaredMethods": true
}]

Complex Configuration

There may be more different cases, like generating hints for classes that are package private or just private, also there hint can be used for whole package.

Complex example generating reflection access:

@JniHint(types = { Response.class, Request.class }, value = JniHint.AccessType.ALL_DECLARED_FIELDS)
@JniHint(typeNames = { "io.goodforgod.graalvm.hint.processor"})
public final class JniConfig {

}

Generated jni-config.json:

[{
  "name": "io.goodforgod.graalvm.hint.processor",
  "allDeclaredConstructors": true,
  "allDeclaredFields": true,
  "allDeclaredMethods": true
},
{
  "name": "io.goodforgod.example.Response",
  "allDeclaredFields": true
},
{
  "name": "io.goodforgod.example.Request",
  "allDeclaredFields": true
}]

License

This project licensed under the Apache License 2.0 - see the LICENSE file for details

About

Generates GraalVM configuration hints for native-image applications.

License:Apache License 2.0


Languages

Language:Java 100.0%