Using JMH for Java Microbenchmarking: Demo, Annotations, and Best Practices

This article introduces Java Microbenchmark Harness (JMH), explains why warm‑up is needed, shows how to build a benchmark project with Maven, provides a complete LinkedList iteration benchmark example with all relevant JMH annotations, demonstrates execution commands, and interprets the resulting performance reports.

Top Architect
Top Architect
Top Architect
Using JMH for Java Microbenchmarking: Demo, Annotations, and Best Practices

In daily Java development, measuring the performance of code fragments is essential, but the JVM’s mixed JIT‑and‑interpreter execution makes raw timing unreliable, so a warm‑up phase is recommended before taking measurements.

JMH (Java Microbenchmark Harness) is the official OpenJDK tool for writing micro‑benchmarks with precision down to microseconds. It provides a set of annotations such as @Benchmark, @BenchmarkMode, @Warmup, @Measurement, @Threads, @Fork, @OutputTimeUnit, @Setup, @TearDown, @State, and @Param to control every aspect of a benchmark.

Project setup

For a quick start you can generate a JMH project with Maven:

$ mvn archetype:generate \
          -DinteractiveMode=false \
          -DarchetypeGroupId=org.openjdk.jmh \
          -DarchetypeArtifactId=jmh-java-benchmark-archetype \
          -DgroupId=org.sample \
          -DartifactId=test \
          -Dversion=1.0

Alternatively add the dependencies to an existing Maven project:

<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>
    <scope>provided</scope>
</dependency>

Benchmark example

@State(Scope.Benchmark)
@OutputTimeUnit(TimeUnit.SECONDS)
@Threads(Threads.MAX)
public class LinkedListIterationBenchMark {
    private static final int SIZE = 10000;
    List<String> list = new LinkedList<>();

    @Setup
    public void setUp() {
        for (int i = 0; i < SIZE; i++) {
            list.add(String.valueOf(i));
        }
    }

    @Benchmark
    @BenchmarkMode(Mode.Throughput)
    public void forIndexIterate() {
        for (int i = 0; i < list.size(); i++) {
            list.get(i);
            System.out.print("");
        }
    }

    @Benchmark
    @BenchmarkMode(Mode.Throughput)
    public void forEachIterate() {
        for (String s : list) {
            System.out.print("");
        }
    }
}

Running the benchmark

From the command line you can build the JAR and execute it:

$ mvn clean install
$ java -jar target/benchmarks.jar

Or run it directly from a main method:

public static void main(String[] args) throws RunnerException {
    Options opt = new OptionsBuilder()
            .include(LinkedListIterationBenchMark.class.getSimpleName())
            .forks(1)
            .warmupIterations(2)
            .measurementIterations(2)
            .output("E:/Benchmark.log")
            .build();
    new Runner(opt).run();
}

The output shows throughput (operations per second) for each benchmark method, e.g.:

Benchmark                                 Mode  Cnt   Score   Error  Units
LinkedListIterationBenchMark.forEachIterate   thrpt   2  1192.380          ops/s
LinkedListIterationBenchMark.forIndexIterate   thrpt   2   206.866          ops/s

Annotation details @BenchmarkMode – selects the measurement type (Throughput, AverageTime, etc.). @Warmup – number of warm‑up iterations before real measurement. @Measurement – number of measurement iterations and their duration. @Threads – how many threads run the benchmark concurrently. @Fork – how many separate JVM forks are used. @OutputTimeUnit – unit for reporting results. @Setup / @TearDown – code executed before/after each benchmark iteration. @State – defines the scope of shared state (Thread, Group, Benchmark). @Param – supplies multiple values for a field to test different inputs.

JMH can be applied to benchmark logging frameworks, bean‑copy utilities, or any Java component where precise performance data is required.

For more examples, refer to the official JMH samples repository:

https://hg.openjdk.java.net/code-tools/jmh/file/tip/jmh-samples/src/main/java/org/openjdk/jmh/samples/
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

javaPerformance TestingmavenannotationsBenchmarkingmicrobenchmarkJMH
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.