5

I've just upgraded several projects to Java 19, Spring Boot 3.0.2, Kotlin 1.8.0 with Maven and I'd like Spring Boot to generate native images.

<java.version>19</java.version>
<kotlin.version>1.8.0</kotlin.version>

The relevant part of the configuration of spring-boot-maven-plugin is:

        <configuration>
          <image>
            <env>
              <BP_JVM_VERSION>19.*</BP_JVM_VERSION>
              <BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE>
              <BPE_APPEND_JAVA_TOOL_OPTIONS>-XX:+HeapDumpOnOutOfMemoryError -XX:MaxDirectMemorySize=64M</BPE_APPEND_JAVA_TOOL_OPTIONS>
              <BPE_DELIM_JAVA_TOOL_OPTIONS xml:space="preserve"> </BPE_DELIM_JAVA_TOOL_OPTIONS>
            </env>
          </image>
        </configuration>

However, when I build one of the projects with

mvn -Pnative spring-boot:build-image

then the build fails with the following error message:

[INFO]     [creator]     Paketo Buildpack for BellSoft Liberica 9.10.2
[INFO]     [creator]       unable to find dependency
[INFO]     [creator]       no valid dependencies for native-image-svm, 19.*, and io.paketo.stacks.tiny in [(jdk, 8.0.362, [io.buildpacks.stacks.bionic io.paketo.stacks.tiny *]) (jre, 8.0.362, [io.buildpacks.stacks.bionic io.paketo.stacks.tiny *]) (jdk, 11.0.18, [io.buildpacks.stacks.bionic io.paketo.stacks.tiny *]) (jre, 11.0.18, [io.buildpacks.stacks.bionic io.paketo.stacks.tiny *]) (native-image-svm, 11.0.17, [io.buildpacks.stacks.bionic io.paketo.stacks.tiny *]) (jdk, 17.0.6, [io.buildpacks.stacks.bionic io.paketo.stacks.tiny *]) (jre, 17.0.6, [io.buildpacks.stacks.bionic io.paketo.stacks.tiny *]) (native-image-svm, 17.0.5, [io.buildpacks.stacks.bionic io.paketo.stacks.tiny *]) (jdk, 19.0.2, [io.buildpacks.stacks.bionic io.paketo.stacks.tiny *]) (jre, 19.0.2, [io.buildpacks.stacks.bionic io.paketo.stacks.tiny *])]
[INFO]     [creator]     ERROR: failed to build: exit status 1

What's missing?

Update: When I downgrade to Java 17 with Kotlin 1.7.21, then the build succeeds and apparently there's no support yet in the Liberica Native Image Kit for Java 19. https://bell-sw.com/pages/downloads/native-image-kit/#/nik-22-19

Andras Hatvani
  • 4,346
  • 4
  • 29
  • 45

5 Answers5

3

Let me provide you with alternatives to downgrading your Java version (in case you e.g. want to use virtual threads).

You might be successful using GraalVM instead of Liberica NIK. You can configure this in your pom.xml as described in the section Use an alternative native image toolkit of the Spring Boot Documentation:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <image>
            <buildpacks>
                <buildpack>gcr.io/paketo-buildpacks/graalvm</buildpack>
                <buildpack>gcr.io/paketo-buildpacks/java-native-image</buildpack>
            </buildpacks>
        </image>
    </configuration>
</plugin>

Since The GraalVM Buildpack supports Java 19, you should be able to use it:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <image>
            <buildpacks>
                <buildpack>gcr.io/paketo-buildpacks/graalvm</buildpack>
                <buildpack>gcr.io/paketo-buildpacks/java-native-image</buildpack>
            </buildpacks>
            <env>
                <BP_JVM_VERSION>19.0.1</BP_JVM_VERSION>
            </env>
        </image>
    </configuration>
</plugin>

As an alternative, it would be possible to not use buildpacks for creating the native image but instead create a native executable using mvn -Pnative package See Getting started with Native Build Tools.

Then, you could create your own docker image (e.g. using a Dockerfile or similar) and include that.

dan1st
  • 12,568
  • 8
  • 34
  • 67
3

Just note, that the Maven configuration above might not be enough, because you also need to define the supported JVM version matching your GraalVM version. Also a BP_NATIVE_IMAGE=true environment variable is required.

The GraalVM buildpack released defined here. Based on that JVM version 19.0.1 is not supported. I had to upgrade to GraalVM 22.3.1:

https://github.com/paketo-buildpacks/graalvm/releases

Based on that the GraalVM version 22.3 can be used by the following Maven config. I had success with GraalVM 22.3.1 running JDK 19.0.2

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <image>
            <buildpacks>
                <buildpack>gcr.io/paketo-buildpacks/graalvm</buildpack>
                <buildpack>gcr.io/paketo-buildpacks/java-native-image</buildpack>
            </buildpacks>
            <env>
                <BP_JVM_VERSION>19.0.2</BP_JVM_VERSION>
                <BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE>
            </env>
        </image>
    </configuration>
</plugin>

The list of supported GraalVM versions can be found in Paketo's website, but it's not kept up-to-date with the GraalVM buildpack releases.

For further info see GraalVM release notes below:

Also see the spring-boot-maven-plugin config documentation for further reference on the parameters.

Oresztesz
  • 2,294
  • 1
  • 15
  • 26
  • Are you sure about `17.0.4`? It should use Java 19 after all... – dan1st Mar 17 '23 at 18:01
  • I'm not sure, but look at the GraalVM release notes. You can only have Java 19 from GraalVM 22.3.x. I had similar error above, when trying to use the paketo buildpack with GraalVM 22.3.r19 – Oresztesz Mar 17 '23 at 18:04
  • Using a new GraalVM version would probably not help much if you tell it to use Java 17 - I think you should tell it to use Java 19 instead of Java 17. And doesn't it use the latest version by default? – dan1st Mar 17 '23 at 18:12
  • OK, let me try to specify both graalvm and java-native-image buildpack version. My build has trouble with the java-native-image buildpack actually. – Oresztesz Mar 17 '23 at 18:15
  • 1
    In one of my projects, it used `22.3.1` without me explicitely specifying it (although I use Java 17 and not Java 19). – dan1st Mar 17 '23 at 18:22
  • @dan1st - FYI I was able to proceed but only with the config above. No luck with JVM 19.0.1 – Oresztesz Mar 20 '23 at 13:42
1

When I downgrade to Java 17 with Kotlin 1.7.21, then the build succeeds and apparently there's no support yet in the Liberica Native Image Kit for Java 19. https://bell-sw.com/pages/downloads/native-image-kit/#/nik-22-19.

Furthermore, it's stated on the same page:

  1. What Java versions are supported by NIK?

Two latest Java LTS versions, Java 11 and Java 17, are supported by Liberica NIK.

Andras Hatvani
  • 4,346
  • 4
  • 29
  • 45
1

I have generated an answer for Kotlin DSL Gradle based on Oresztesz's answer.

tasks.withType<org.springframework.boot.gradle.tasks.bundling.BootBuildImage> {
    builder.set("paketobuildpacks/builder:tiny")

    environment.set(
        mapOf(
            "BP_JVM_VERSION" to "19.0.2",
            "BP_NATIVE_IMAGE" to "true",
        ),
    )

    buildpacks.set(
        listOf(
            "gcr.io/paketo-buildpacks/graalvm",
            "gcr.io/paketo-buildpacks/java-native-image",
        ),
    )
}
Minchul Joh
  • 33
  • 1
  • 9
0

In addition to the above, if you'd like to use preview features such as Virtual Threads in Java 19, the --enable-preview argument is needed:

<image>
  <buildpacks>
    <buildpack>gcr.io/paketo-buildpacks/graalvm</buildpack>
    <buildpack>gcr.io/paketo-buildpacks/java-native-image</buildpack>
  </buildpacks>
  <env>
    <BP_JVM_VERSION>19.0.2</BP_JVM_VERSION>
    <BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE>
    <BP_NATIVE_IMAGE_BUILD_ARGUMENTS>--enable-preview</BP_NATIVE_IMAGE_BUILD_ARGUMENTS>
  </env>
</image>