3

JMH recommends you use their archetype to create a project. I am able to run my benchmark code this way by including my code to be benchmarked as a dependency in this generated project.

However, I'm now trying to integrate the benchmarks directly in my project source using a profile

<profiles>
    <profile>
        <id>benchmark</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-shade-plugin</artifactId>
                    <version>2.2</version>
                    <executions>
                        <execution>
                            <phase>package</phase>
                            <goals>
                                <goal>shade</goal>
                            </goals>
                            <configuration>
                                <finalName>${uberjar.name}</finalName>
                                <transformers>
                                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                        <mainClass>org.openjdk.jmh.Main</mainClass>
                                    </transformer>
                                </transformers>
                                <filters>
                                    <filter>
                                        <!--
                                            Shading signed JARs will fail without this.
                                            http://stackoverflow.com/questions/999489/invalid-signature-file-when-attempting-to-run-a-jar
                                        -->
                                        <artifact>*:*</artifact>
                                        <excludes>
                                            <exclude>META-INF/*.SF</exclude>
                                            <exclude>META-INF/*.DSA</exclude>
                                            <exclude>META-INF/*.RSA</exclude>
                                        </excludes>
                                    </filter>
                                </filters>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
        <dependencies>
            <dependency>
                <groupId>org.openjdk.jmh</groupId>
                <artifactId>jmh-core</artifactId>
                <version>${jmh.version}</version>
            </dependency>
            <dependency>
                <groupId>org.openjdk.jmh</groupId>
                <artifactId>jmh-generator-annprocess</artifactId>
                <version>${jmh.version}</version>
            </dependency>
        </dependencies>
    </profile>
</profiles>

When I do this and run the generated benchmark jar I get an IncompatibleClassChangeError

Exception in thread "main" java.lang.IncompatibleClassChangeError: Implementing class
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
    at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    at org.openjdk.jmh.Main.main(Main.java:44)

Any pointers would be highly appreciated

qwerty
  • 3,801
  • 2
  • 28
  • 43
  • 1
    Please provide a MCVE: http://stackoverflow.com/help/mcve. Otherwise, this looks like a build configuration gone wrong, and benchmarks that JMH had generated -- and those that reference the project classes -- got desynced with the rest of the project, after project classes changed. See e.g.: http://stackoverflow.com/questions/1980452/what-causes-java-lang-incompatibleclasschangeerror – Aleksey Shipilev Mar 29 '16 at 21:28

1 Answers1

2

You really need JMH with a separate pom. I would use the maven invoker plugin to invoke it.

Alun
  • 541
  • 6
  • 16
  • Does JMH need to be a totally separate project with its own pom or can it be a module with a pom as a child of the main project ? – Freiheit Jun 03 '17 at 01:19
  • 3
    "The recommended way to run a JMH benchmark is to use Maven to setup a standalone project that depends on the jar files of your application. This approach is preferred to ensure that the benchmarks are correctly initialized and produce reliable results. It is possible to run benchmarks from within an existing project, and even from within an IDE, however setup is more complex and the results are less reliable." – Alun Jun 05 '17 at 03:11