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.