如何让JMH运行在Dry-Run模式?解决kotlinx-benchmark测试慢问题
让JMH进入Dry-Run模式(仅加载基准不执行)
针对修复kotlinx-benchmark时需要验证配置加载、基准选择逻辑,却不想实际执行耗时基准测试的场景,有两种可靠解决路径:
方案一:利用JMH内置Dry-Run系统属性
JMH内部为自身测试流程提供了jmh.dry.run系统属性,启用后会完整执行配置解析、基准类加载、目标基准选择的全流程,但会跳过实际的基准测试执行,直接返回伪造的测试结果(如0ms)。
使用时只需在JVM启动参数中添加:
-Djmh.dry.run=true
集成到kotlinx-benchmark的代码里,可通过OptionsBuilder直接注入该参数:
val options = OptionsBuilder() .warmupForks(3) .forks(2) .mode(Mode.Throughput) .resultFormat(ResultFormatType.TEXT) .jvmArgs("-Djmh.dry.run=true") // 启用Dry-Run模式 .build()
该方案完全基于JMH原生支持,无需修改框架核心代码,既能准确验证配置传递、基准选择的正确性,又能彻底规避耗时的测试执行。
方案二:自定义类注入覆盖JMH执行逻辑
如果需要更灵活的结果伪造逻辑,可以通过字节码注入或依赖替换的方式,覆盖JMH的核心执行类,阻止真实测试运行。
具体步骤:
- 自定义类继承JMH的
BenchmarkTask,重写call()方法,直接返回预设的伪造Result对象,跳过真实基准执行逻辑。 - 使用字节码工具(如ByteBuddy)在运行时替换JMH原有的
BenchmarkTask实现,或在测试依赖中优先加载自定义类。
示例伪代码(基于ByteBuddy):
import net.bytebuddy.ByteBuddy import net.bytebuddy.implementation.FixedValue import net.bytebuddy.matcher.ElementMatchers.named import org.openjdk.jmh.runner.tasks.BenchmarkTask import org.openjdk.jmh.results.RunResult fun setupDryRun() { // 构造伪造的RunResult对象 val fakeResult = RunResult(/* 填充必要的基准元数据 */) ByteBuddy() .redefine(BenchmarkTask::class.java) .method(named("call")) .intercept(FixedValue.value(fakeResult)) .make() .load(BenchmarkTask::class.java.classLoader, ClassReloadingStrategy.fromInstalledAgent()) }
此方案需要额外引入字节码工具依赖,且对JMH版本有兼容性要求,推荐优先使用方案一。
内容的提问来源于stack exchange,提问作者aSemy
相关产品推荐
相关产品推荐

