You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用JMH对包含库导入耗时的Java代码进行基准测试?

JMH基准测试:关于“库导入开销”的真相

先搞清楚一个关键事实:Java里的import语句完全没有运行时开销。它只是编译阶段的语法糖——让你写代码时不用反复写全限定类名(比如直接写List而非java.util.List),编译后的字节码里所有类引用都是全限定名,和导入语句半毛钱关系都没有。所以不存在“把库导入和代码一起基准测试”的说法,因为导入本身根本不影响运行时性能。

如果你实际想测的是首次加载某个类时的JVM类加载开销(比如第一次用IntStream或Collections时JVM加载这些类的耗时),这和导入语句无关,但可以用JMH来测试,具体做法如下:

因为JMH默认会执行预热迭代,预热时类就会被加载,正式测试就测不到加载开销了,所以要做以下调整:

  • 用@Fork让每个测试在独立JVM进程运行,确保每次测试都是全新的类加载环境
  • 关闭预热,确保测试时类是首次被加载
  • 用SingleShotTime模式测单次执行的开销(类加载只发生一次)

示例代码:

package org.example;

import org.openjdk.jmh.annotations.*;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@Fork(value = 1) // 每个测试fork新JVM,避免类加载状态复用
public class ClassLoadBenchmark {

    // 测试首次加载类+执行逻辑的总开销
    @Benchmark
    @BenchmarkMode(Mode.SingleShotTime)
    @Warmup(iterations = 0) // 关闭预热,确保类首次加载
    public void bench_FirstRunWithClassLoad() {
        List<Integer> pages = IntStream.range(0, 256).boxed().collect(Collectors.toList());
        Collections.shuffle(pages);
    }

    // 对比基准:仅测逻辑本身的开销(类已提前加载完成)
    @Benchmark
    @BenchmarkMode(Mode.AverageTime)
    @Warmup(iterations = 5) // 预热让类加载完成
    @Measurement(iterations = 10)
    public void bench_LogicOnly() {
        List<Integer> pages = IntStream.range(0, 256).boxed().collect(Collectors.toList());
        Collections.shuffle(pages);
    }

    public static void main(String[] args) throws Exception {
        org.openjdk.jmh.Main.main(args);
    }
}

运行后对比两个基准的结果,差值就是首次类加载带来的额外开销。

内容的提问来源于stack exchange,提问作者Ymi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 20:55:19