如何不借助melix/jmh-gradle-plugin在Kotlin中运行JMH基准测试?
解决JMH无法识别Kotlin基准测试类的问题
问题根源
JMH扫不到Kotlin写的基准类,本质是这几个环节没做好:
- Kotlin编译后的类文件没加入任务的类路径
- JMH注解处理器没处理Kotlin源码,没生成必要的支撑类
- Kotlin类默认是final的,JMH无法生成子类来执行基准测试(针对带
@State的类)
Gradle配置方案(Kotlin DSL)
1. 引入必要依赖
先确保你的build.gradle.kts里包含JMH和Kotlin的核心依赖,同时加上注解处理器:
dependencies { implementation(kotlin("stdlib")) // JMH核心库 implementation("org.openjdk.jmh:jmh-core:1.37") // JMH注解处理器,生成基准测试所需的动态类 annotationProcessor("org.openjdk.jmh:jmh-generator-annprocess:1.37") // 给Kotlin代码用的注解处理器,确保Kotlin注解被正确处理 kapt("org.openjdk.jmh:jmh-generator-annprocess:1.37") }
2. 配置runBenchmark任务
注册一个JavaExec类型的任务,把所有必要的类路径都加上,指定JMH的入口类:
tasks.register<JavaExec>("runBenchmark") { group = "Benchmark" description = "Run JMH benchmarks written in Kotlin" // JMH的主入口类 mainClass.set("org.openjdk.jmh.Main") // 类路径必须包含:编译后的Kotlin/Java类、JMH依赖、注解处理器生成的类 classpath = sourceSets.main.get().runtimeClasspath + sourceSets.main.get().output + configurations.annotationProcessor // 自定义JMH运行参数,比如迭代次数、预热次数,按需调整 args("-v", "-f", "1", "-wi", "5", "-i", "5") } // 确保编译和注解处理完成后再跑基准测试 tasks.named("runBenchmark") { dependsOn(tasks.compileKotlin, tasks.compileJava, tasks.processResources) }
3. 处理Kotlin类的final问题
JMH需要给带@State注解的类生成子类,但Kotlin类默认是final的,二选一解决:
- 手动给
@State类加open关键字:
import org.openjdk.jmh.annotations.* @State(Scope.Thread) open class MyKotlinBenchmark { @Benchmark fun testMyOperation() { // 你的基准测试逻辑 } }
- 用
all-open插件自动处理:
在build.gradle.kts的plugins块里添加:
plugins { kotlin("jvm") version "1.9.20" id("org.jetbrains.kotlin.plugin.allopen") version "1.9.20" } allOpen { // 让所有带@State注解的类自动变为open annotation("org.openjdk.jmh.annotations.State") }
验证方法
- 执行命令
gradle lib:runBenchmark(替换lib为你的子模块名) - 如果还是扫不到类,用
gradle lib:runBenchmark --debug查看类路径,确认Kotlin编译后的build/classes/kotlin/main目录是否在类路径中 - 检查Kotlin代码里的注解是否正确导入,别写错包名
内容的提问来源于stack exchange,提问作者Stanley Wintergreen
相关产品推荐
相关产品推荐

