-
Notifications
You must be signed in to change notification settings - Fork 98
Description
Environment
- JDK: 21
- Kotlin: 2.2.x (Kotlin/JVM)
- AspectJ: aspectjweaver 1.9.24, aspectjrt 1.9.24
- Build tool: Gradle (Kotlin DSL), tests run with
-javaagent:aspectjweaver.jar(LTW)
Problem
Load-time weaving with aspectjweaver fails (or produces bytecode that fails verification) when advising Kotlin suspend functions compiled into coroutine state machines.
The same setup works for “simple” suspend functions without a state machine (e.g., a single suspend call).
Minimal reproducer
A minimal Gradle Kotlin project.
It contains:
- A custom annotation (e.g.,
@MyAnnotation) to match the pointcut. - An annotation-style aspect (
@Aspect) with@Before,@AfterReturning,@AfterThrowingadvices on execution(@MyAnnotation* *(..)). - A JUnit5 test using
runTest.
Kotlin code (simplified):
@Test
fun test() = runTest { fun2() }
@MyAnnotation
suspend fun fun1() { coroutineContext }
@MyAnnotation
suspend fun fun2() {
fun1()
fun1() // removing this line makes the problem disappear
}Observed behavior
The resulting woven class fails with either:
java.lang.VerifyError: Expecting a stackmap frame at branch target ...at class load time, or- an internal weaving error like
AspectJ Internal Error: unable to add stackmap attributes ...with stack traces pointing to StackMapAdder / ASM Frame.merge (depending on the exact execution path).
Bytecode evidence (before/after)
I enabled LTW class dumping to capture woven classes. This produces _ajdump/_before/.../AspectTest.class and _ajdump/.../AspectTest.class.
Using javap -c -v, the before method contains a valid StackMapTable with multiple entries (Kotlin-generated state machine), while in the after version the control-flow is modified (try/catch + epilogue + gotos), and the resulting class appears to have missing or inconsistent stack map frames, leading to verification failure.
I can attach:
_ajdump/_before/.../*.classand_ajdump/.../*.classjavap -c -voutputs forfun2(Continuation)before and after weaving- Full Gradle project.
Expected behavior
LTW correctly recomputes/emits StackMapTable for the woven coroutine state machine methods, producing verifiable bytecode on JDK 21
Notes
This is not about advising Kotlin source code directly (Kotlin is compiled by kotlinc first). The issue is strictly about weaving already-compiled .class files generated by Kotlin for suspend state machines.