I've added SIMD code to a Java application that uses Maven to build, and now I have to run it like this:
mvn exec:java -Dexec.mainClass="com.path.to.app.MainClass" -Dexec.classpathScope=runtime -Dexec.systemProperties="-da --add-modules=jdk.incubator.vector"
I also created .mvn/jvm.config
file with the following content:
--add-modules=jdk.incubator.vector
Finally, in pom.xml
I added the following under project/build/plugins
:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<compilerArgs>
<arg>--add-modules=jdk.incubator.vector</arg>
</compilerArgs>
</configuration>
</plugin>
The application itself runs from Eclipse and from command-line with Maven as shown above. However, if I run mvn install
, the JUnit tests fail:
java.lang.NoClassDefFoundError: jdk/incubator/vector/Vector
...
Caused by: java.lang.ClassNotFoundException: jdk.incubator.vector.Vector
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
All the above steps were found on the internet. I couldn't find how to fix JUnit. Please, suggest.
OpenJDK 19, Maven 3.8.6, Ubuntu 20.04, JUnit is enabled in pom.xml
as follows:
<junit.version>4.13.2</junit.version>
...
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
CodePudding user response:
As far as I can judge, the compilation is fine. That means the maven-compiler-plugin
is properly configured, i.e. <arg>--add-modules=jdk.incubator.vector</arg>
is picked up.
The java.lang.NoClassDefFoundError
happens at runtime, i.e. when the test is running. That obviously means --add-modules=jdk.incubator.vector
is not picked up. I believe the reason is the maven-surefire-plugin
not configured properly so that it doesn't propagate that value to the JVM that actually runs the test. By default, that JVM is different from the one running Maven itself. This is managed by the forkCount
parameter:
The default setting is forkCount=1/reuseForks=true, which means that maven-surefire-plugin creates one new JVM process to execute all tests in one Maven module.
So, if you want to keep it that way (forkCount
> 0) then you have to properly configure the maven-surefire-plugin
. Like in the following example:
<plugins>
[...]
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M7</version> <!-- pick your own version -->
<configuration>
<forkCount>1</forkCount>
<argLine>--add-modules=jdk.incubator.vector</argLine>
</configuration>
</plugin>
[...]
</plugins>
.mvn/jvm.config
doesn't work in your case because this configuration is for Maven JVM as sort of alternative for MAVEN_OPTS:
So no need anymore for MAVEN_OPTS... You don't need to use these options in MAVEN_OPTS or switch between different configurations.
About MAVEN_OPTS:
This variable contains parameters used to start up the JVM running Maven and can be used to supply additional options to it.
So, if forking is disabled (forkCount
= 0) then it will work because there will be only one JVM for everything. Otherwise, only the system properties get passed to a forked JVM:
System property variables from the main maven process are passed to the forked process as well.