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

Kotlin内联高阶函数结合Hibernate触发VerifyError问题求助

Kotlin Inline Reified Enum Function Triggers VerifyError in Gradle bootRun but Works in IntelliJ

Problem Context

I'm working with a Kotlin + Spring + Hibernate stack, and hit a java.lang.VerifyError: Bad return type error when running my app via ./gradlew bootRun. Oddly enough, the exact same code runs flawlessly when using IntelliJ's built-in Run feature. The suspect code is this enum and inline helper function:

inline fun <reified T : Enum<T>> generateGetter(unknownValue: T): (String) -> T {
    return { s ->
        var res = unknownValue
        for (v in enumValues<T>()) {
            if (s == v.name) {
                res = v
                break
            }
        }
        res
    }
}
enum class Degree {
    Unknown, HighSchool, Bachelor, Master;
    companion object {
        val getEnum = generateGetter(Unknown)
    }
}

Root Cause

This issue stems from how Kotlin's inline reified functions interact with Spring Boot's Gradle plugin and JVM bytecode verification:

  • When using a reified generic in an inline function, the Kotlin compiler replaces the generic type with the concrete enum type (Degree in this case) at compile time.
  • The Spring Boot Gradle plugin (specifically the bootRun/bootJar tasks) applies extra bytecode processing and repackaging logic. During this process, the bytecode generated for the lambda returned by generateGetter ends up with a type signature that fails strict JVM bytecode verification.
  • IntelliJ's Run feature skips this additional bytecode processing and uses raw class files directly from the Kotlin compiler. The JVM's validator is either less strict in this scenario, or the simpler class loading order avoids triggering the type mismatch check.

Solutions

Here are two reliable fixes to resolve this error:

1. Replace Inline Reified Function with Non-Inline Version

Remove the inline and reified modifiers, and pass the enum class explicitly as a parameter. This avoids the bytecode generation issues caused by reified generics in this context:

fun <T : Enum<T>> generateGetter(unknownValue: T, enumClass: Class<T>): (String) -> T {
    return { s ->
        enumClass.enumConstants.firstOrNull { it.name == s } ?: unknownValue
    }
}

enum class Degree {
    Unknown, HighSchool, Bachelor, Master;
    companion object {
        val getEnum = generateGetter(Unknown, Degree::class.java)
    }
}

2. Inline the Logic Directly in the Companion Object

Skip the helper function entirely and implement the enum lookup logic directly in the companion object. This is the simplest approach for this use case:

enum class Degree {
    Unknown, HighSchool, Bachelor, Master;
    companion object {
        val getEnum = { s: String ->
            enumValues<Degree>().firstOrNull { it.name == s } ?: Unknown
        }
    }
}

Why IntelliJ Works but Gradle Doesn't

IntelliJ's Run configuration uses unmodified class files from the Kotlin compiler, without applying Spring Boot's repackaging or bytecode optimizations. The JVM doesn't trigger the verification error here because the class loading structure is simpler. Gradle's bootRun uses Spring Boot's launcher to load processed classes, where the strict bytecode validator catches the type mismatch introduced by the combination of inline reified generics and Spring's bytecode handling.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 11:22:50