Table of contents
  1. TidBits
    1. Create Graal Native Image
    2. using the following to generate reflection meta-data
  2. Reflective Acccess
    1. Run Native Image In Dev
  3. Reflective Access
  4. GraalVM annotation processor
  5. TidBits
    1. Bug with GraalVM and Java Records
  6. Gradle
    1. Method to check if GraalVM JDK Distribution
    2. add tool chain to gradle
      1. get java toolchains
  7. Plugins
  8. Resources




TidBits

Create Graal Native Image

    ./gradlew nativeCompile

using the following to generate reflection meta-data

     java -agentlib:native-image-agent=config-output-dir=./META-INF/native-image -jar your-micronaut-app.jar

Reflective Acccess

add a reflect-config.jsonfor refelctive access

to /src/main/resources/META-INF/native-image/[package]

Run Native Image In Dev

    ./build/native/nativeCompile/graal-mail -Dmicronaut.environments=dev

Reflective Access

add a reflect-config.json so Graal recognizes imported classes that need to be reflective

touch /src/main/resources/META-INF/native-image/com/ssi/reflect-config.json

MicroStream Source Reference

{
  "name": "fts.marketing.utils.deserializers.CampaignEmailStatusDeserializer",
  "allDeclaredConstructors": true,
  "allPublicConstructors": true,
  "allDeclaredMethods": true,
  "allPublicMethods": true,
  "allDeclaredClasses": true,
  "allPublicClasses": true
}

GraalVM annotation processor

gradle import

annotationProcessor("io.micronaut:micronaut-graal")

This processor generates additional classes that implement the GraalReflectionConfigurer Interface and programmatically register reflection configuration.

Example Class:


@ReflectiveAccess
@Serdeable
public class Integration {
    //code
}
If you have more advanced requirements and only wish to include certain fields or methods, use the annotation on any constructor, field or method to include only the specific field, constructor or method.

TidBits

Bug with GraalVM and Java Records

include the flag when building the native executable

--report-unsupported-elements-at-runtime

Create the file native-image.properties at

src/main/resources/META-INF/native-image/example.micronaut/guide/native-image.properties

MY Example, only line in text file

Args = --report-unsupported-elements-at-runtime

Gradle

The Gradle plugin has a new testNativeImage task that builds the GraalVM Native Image and uses the native application as an embedded
server enabling the ability to write native integration tests.

Method to check if GraalVM JDK Distribution

Method to check if you are running in GraalVM JDK distribution. I have used it often in Gradle build files to decide whether a Gradle task should be
enabled.

public class GraalStuff {
    private static boolean isGraalVMJava() {
        return (System.getProperty("java.home") != null && Files.exists(Paths.get("${System.getProperty("java.home")}/lib/graalvm")))
                || Arrays.asList("jvmci.Compiler", "java.vendor.version", "java.vendor")
                         .stream()
                         .anyMatch(propertyName -> {
                             String value = System.getProperty(propertyName);
                             return value != null && value.toLowerCase(Locale.ENGLISH)
                                                          .contains("graal");
                         });
    }
}

add tool chain to gradle

You can already build a native executable by running ./gradlew nativeCompile or run it directly by invoking ./gradlew nativeRun
However, at this stage, running the native executable will fail because
this application requires additional metadata: you need to provide it with a list of resources to load.

Instruct the plugin to automatically detect resources to be included in the native executable. Add this to your build.gradle file:

graalvmNative {
    binaries.all {
        resources.autodetect()
    }
    toolchainDetection = false
}

Another thing to note here, the plugin may not be able to properly detect the GraalVM installation because of limitations in Gradle.
By default, the plugin selects a Java 11 GraalVM Community Edition
If you want to use GraalVM Enterprise, or a particular version of GraalVM and Java, you need to explicitly tell in plugin’s configuration.
For example:

graalvmNative {
    binaries {
        main(({
            javaLauncher = javaToolchains.launcherFor {
                languageVersion = JavaLanguageVersion.of(8)
                vendor = JvmVendorSpec.matching("GraalVM Community")
            }
        } as java.lang.String))
    }
}

my working example

graalvmNative {
    toolchainDetection = false

    binaries {
        main(({
            javaLauncher = javaToolchains.launcherFor {
                languageVersion = JavaLanguageVersion.of(17)
                vendor = JvmVendorSpec.matching("GraalVM Community")
            }
            imageName.set('graal-vm-ssi')
            buildArgs.add('--verbose')
        } as java.lang.String))
    }
}

The workaround to this is to disable toolchain detection with this command

toolchainDetection = false

get java toolchains

./gradlew-q javaToolchains

output

Oracle JDK 11.0.18+9-LTS-jvmci-22.3-b11
  | Location:           /Library/Java/JavaVirtualMachines/graalvm-ee-java11-22.3.1/Contents/Home
  | Language Version:   11
  | Vendor:             Oracle
  | Architecture:       x86_64
  | Is JDK:             true
  | Detected by:        Current JVM

Plugins

Resources