如何在Maven中运行JMH基准测试使用exec:java而不是exec:exec?

rol*_*lve 10 java maven jmh

这篇关于javapapers.com的文章展示了如何通过输入在Maven中运行JMH基准测试mvn exec:exec.在Maven中运行JMH非常方便,因为您可以从Eclipse Run Configuration甚至Maven阶段轻松运行它.

但是,此设置存在两个问题:

  1. 当您杀死Maven时,JMH将继续在后台运行,因为exec:exec它在一个单独的VM中启动.

  2. 通常,JMH将启动另一个 VM来运行基准测试,因此您最终将同时运行至少3个VM.

幸运的是,Exec Maven Plugin带来了第二个目标exec:java,它直接在VM Maven运行中执行主类.但是,当我尝试配置Maven以使用JMH时exec:java,由于缺少类,基准测试崩溃:

# 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>
Run Code Online (Sandbox Code Playgroud)

以下是相关部分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>
Run Code Online (Sandbox Code Playgroud)

以下是我如何运行JMH 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();
}
Run Code Online (Sandbox Code Playgroud)

我意识到JMH使用java.class.pathsystem属性来确定分叉VM的类路径,并且该属性不包含Maven的项目依赖项.但是,处理这个问题的首选方法是什么?

rol*_*lve 5

解决此问题的一种方法是my.Benchmark在从main方法调用JMH之前从类的类加载器中提取"有效"类路径:

URLClassLoader classLoader = (URLClassLoader) my.Benchmark.class.getClassLoader();
StringBuilder classpath = new StringBuilder();
for(URL url : classLoader.getURLs())
    classpath.append(url.getPath()).append(File.pathSeparator);
System.setProperty("java.class.path", classpath.toString());
Run Code Online (Sandbox Code Playgroud)

这似乎有效,但感觉很像一个不应该是必要的黑客......


rol*_*lve 5

虽然我之前的回答需要修改基准程序,但这是一个仅限POM的解决方案,它借助Dependency Pluginjava.class.path系统属性设置为runtime类路径:

<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>
Run Code Online (Sandbox Code Playgroud)