This post on javapapers.com shows how to run a JMH benchmark in Maven by typing mvn exec:exec
. Running JMH within Maven is pretty handy, since you can easily run it from an Eclipse Run Configuration or even in a Maven phase.
However, there are two problems with this setup:
When you kill Maven, JMH will continue running in the background, as exec:exec
starts it in a separate VM.
Usually, JMH will start yet another VM to run the benchmarks, so you will end up with at least 3 VMs running at the same time.
Fortunately, the Exec Maven Plugin comes with a second goal, exec:java
, which executes a main class directly in the VM Maven runs. However, when I tried to configure Maven to run JMH using exec:java
, the benchmark crashes because of missing classes:
# JMH 1.11.3 (released 40 days ago)
# VM version: Error: Could not find or load main class org.openjdk.jmh.runner.VersionMain
# VM invoker: C:\Program Files\Java\jdk1.7.0\jre\bin\java.exe
[...]
# Run progress: 0.00% complete, ETA 00:02:40
# Fork: 1 of 1
Error: Could not find or load main class org.openjdk.jmh.runner.ForkedMain
<forked VM failed with exit code 1>
Here is the relevant part of the pom.xml
:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.4.0</version>
<configuration>
<mainClass>my.Benchmark</mainClass>
</configuration>
</plugin>
And here is how I run JMH from my.Benchmark
:
public static void main(String[] args) throws RunnerException {
Options options = new OptionsBuilder().include(my.Benchmark.class.getSimpleName())
.forks(1).build();
new Runner(options).run();
}
I realize that JMH uses the java.class.path
system property to determine the classpath for the forked VMs and that this property does not contain Maven's project dependencies. But what is the preferred way to deal with this?
There are two ways to run the JMH benchmark, uses Maven or run it via a JMH Runner class directly. 3.1 Maven, package it as a JAR and run it via org. openjdk. jmh.
mvn exec:java is a goal from the exec plugin for maven. It lets you specify a main class to execute (see pom. xml). This lets you avoid having to figure out the proper java command to run and classpath arguments and the like.
JMH is a Java harness for building, running, and analysing nano/micro/milli/macro benchmarks written in Java and other languages targetting the JVM.
Maven exec plugin allows us to execute system and Java programs from the maven command. There are two goals of the maven exec plugin: exec:exec - can be used to execute any program in a separate process. exec:java - can be used to run a Java program in the same VM.
While my previous answer requires modifying the benchmark program, here is a POM-only solution that sets the java.class.path
system property to the runtime
classpath with the help of the Dependency Plugin:
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>build-classpath</id>
<goals>
<goal>build-classpath</goal>
</goals>
<configuration>
<includeScope>runtime</includeScope>
<outputProperty>depClasspath</outputProperty>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<configuration>
<mainClass>my.Benchmark</mainClass>
<systemProperties>
<systemProperty>
<key>java.class.path</key>
<value>${project.build.outputDirectory}${path.separator}${depClasspath}</value>
</systemProperty>
</systemProperties>
</configuration>
</plugin>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With