spring-projects / spring-projects/spring-data-commons
Avoid Kotlin reflection in KotlinReflectionUtils.isSuspend for methods without a Continuation parameter
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 838
- Forks
- 730
- PR merge metrics
- No merged PRs in 30d
Description
KotlinReflectionUtils.isSuspend(Method) resolves the KFunction for every Kotlin method it is asked about via ReflectJvmMapping.getKotlinFunction(method). That lookup materializes all members of the declaring KClass through Kotlin reflection (metadata deserialization plus a linear scan comparing javaMethod for each member), only to read KFunction.isSuspend().
AbstractRepositoryMetadata.getReturnType(Method) calls isSuspend for every query method during repository initialization, and RepositoryMethodInvoker calls it again when the invoker is created. For Kotlin repositories that do not use coroutines at all, this is pure overhead: a suspend function always compiles to a JVM method whose last parameter is kotlin.coroutines.Continuation, so a method without such a parameter can never be suspending. Spring Framework's KotlinDetector.isSuspendingFunction(Method) performs exactly that check without loading Kotlin reflection, and QueryExecutionResultHandler in this module already relies on it.
In a Spring Boot 4.2.0-SNAPSHOT / Spring Data 2026.1.0-SNAPSHOT Kotlin application with 243 JPA repositories and 1,418 non-synthetic repository interface methods, a wall-clock startup profile (async-profiler, 2 ms sampling, extracted Boot layout) attributed 241 of 8,694 main-thread samples (2.8 % of startup, about 0.5 s) to KotlinReflectionUtils.isSuspend, all of it below ReflectJvmMapping.getKotlinFunction. A cold-JVM micro-benchmark that calls isSuspend for those 1,418 methods takes 1,146–1,341 ms on current main and 3–4 ms when the Continuation parameter check runs first (5 runs each, JDK 27, Apple M5 Max).
Proposal: short-circuit isSuspend with KotlinDetector.isSuspendingFunction(method) before touching Kotlin reflection, keeping the KFunction.isSuspend() verification for methods that do declare a trailing Continuation parameter so the result stays identical for non-suspending functions that take a Continuation argument explicitly.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at KotlinReflectionUtils.isSuspend(Method), then inspect its callers AbstractRepositoryMetadata.getReturnType(Method) and RepositoryMethodInvoker, along with KotlinDetector.isSuspendingFunction(Method) and QueryExecutionResultHandler. Done means methods without a trailing Continuation avoid Kotlin reflection while methods with one retain the KFunction.isSuspend() verification; run the relevant existing tests.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, kotlin, spring
- Domain
- backend, performance
- Issue type
- Refactor
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100