The Spring Boot Maven Plugin needs a way to provide options within the POM to be provided to the JVM when Java is invoked in an executable JAR using the default launch script.

Some dependencies such as Jansi use native access. In Java 21+, using native access with no further settings will show the following warning:

WARNING: A restricted method in java.lang.System has been called
WARNING: java.lang.System::load has been called by org.fusesource.jansi.internal.JansiLoader in an unnamed module (jar:nested:/R:/work/jordial/baglog/cli/target/bin/baglog/!BOOT-INF/lib/jansi-2.4.2.jar!/)
WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning for callers in this module
WARNING: Restricted methods will be blocked in a future release unless native access is enabled

Read more about this issue in Jansi at fusesource/jansi#301. Read JEP 472 to get the full Java technical details.

I'm using the Spring Boot Maven plugin repackage goal to create an executable JAR with the Spring Boot default script:

<plugin>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-maven-plugin</artifactId>
  <executions>
    <execution>
      <id>generate-exe-jar</id>
      <phase>package</phase>
      <goals>
        <goal>repackage</goal>
      </goals>
      <configuration>
        <layout>JAR</layout>
        <classifier>exe</classifier>
        <mainClass>${exe.main.class}</mainClass>
        <executable>true</executable>
      </configuration>
    </execution>
  </executions>
</plugin>

That generates an executable JAR with a prepended script that invokes Java like this:

…
arguments=(-Dsun.misc.URLClassPath.disableJarChecking=true $JAVA_OPTS -jar "$jarfile" $RUN_ARGS "$@")
…
"$javaexe" "${arguments[@]}"
…

There seems to be no way to add --enable-native-access=ALL-UNNAMED to the JVM arguments.

I tried using embeddedLaunchScriptProperties to override JAVA_OPTS, but no luck: nothing changed.

        <embeddedLaunchScriptProperties>
          <JAVA_OPTS>--enable-native-access=ALL-UNNAMED</JAVA_OPTS>
        </embeddedLaunchScriptProperties>

As an analogy, note that the Launch4J Maven Plugin, which creates a native Windows executable, does provide a way to indicate <opt>--enable-native-access=ALL-UNNAMED</opt> for the JVM:

<plugin>
  <groupId>com.akathist.maven.plugins.launch4j</groupId>
  <artifactId>launch4j-maven-plugin</artifactId>
  <executions>
    <execution>
      <id>generate-exe</id>
      <phase>package</phase>
      <goals>
        <goal>launch4j</goal>
      </goals>
      <configuration>
        <headerType>console</headerType>
        <outfile>${binOutputDirectory}/${exe.filename}</outfile>
        <jar>${project.build.directory}/${project.artifactId}-${project.version}-exe.jar</jar>
        <errTitle>${project.name}</errTitle>
        <downloadUrl>https://adoptium.net/</downloadUrl>
        <jre>
          <path>%JAVA_HOME%;%PATH%</path>
          <minVersion>${maven.compiler.release}</minVersion>
          <opts>
            <opt>--enable-native-access=ALL-UNNAMED</opt>
          </opts>
        </jre>
…

I realize I can create a completely new script, but duplicating the entire script just to provide a JVM option would be a last resource. It doesn't seem unreasonable that the Spring Boot default launch script would provide a way to indicate JVM options, as the Launch4J Maven Plugin does.

Comment From: wilkinsona

You should be able to use inlinedConfScript to point to a file that is then inlined into the launch script at build time. You can set JAVA_OPTS (or whatever else you need) in that script.

Comment From: spring-projects-issues

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

Comment From: garretwilson

You should be able to use inlinedConfScript to point to a file that is then inlined into the launch script at build time. You can set JAVA_OPTS (or whatever else you need) in that script.

Thank you for suggesting a workaround. It may be that inlinedConfScript proves less painful than using embeddedLaunchScript to replace the entire script.

Nevertheless that is a workaround to the feature request I'm raising here. Moreover neither approach will work in my use case. I need to enable this in a parent POM so that this setting automatically is inherited by all the child POMs. It is unreasonable to ask every single POM that extends this parent POM to include some inlined script just to enable some JVM settings.

Quoting from this ticket's description:

It doesn't seem unreasonable that the Spring Boot default launch script would provide a way to indicate JVM options, as the Launch4J Maven Plugin does.

Thank you for considering this feature request.

Comment From: garretwilson

Perhaps the parent POM could actually generate the inlined script in one Maven phase, and then include it in the other, but sincerely, that is a lot of work just to include a few characters of JVM settings, a common and not unreasonable need.

So yes there probably exists some elaborate workaround to get the information I need to the JVM. This feature request is to add a simple setting to provide this information in a simple, concise, and semantically expected manner as the Launch4J Maven Plugin does.