3

When the debugger stops on breakpoint somewhere in Kotlin Coroutines code, I usually suffer from the inability to access local variables values (they are out of scope and inaccessible due to the nature of Coroutines implementation).

Is there any compiler argument or IDEA trick to keep local variables visible over suspend points?

Image showing example of variable was optimized out issue

aksh1618
  • 2,245
  • 18
  • 37
Nikita Tukkel
  • 1,975
  • 1
  • 9
  • 15

2 Answers2

2

You can use -Xdebug in Kotlin version 1.8.

Add it to your build.gradle like this:

Kotlin:

tasks.named("compileKotlin", org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask::class.java) {
    compilerOptions {
        freeCompilerArgs.add("-Xdebug")
    }
}

Groovy:

tasks.named('compileKotlin', KotlinCompilationTask) {
    compilerOptions { 
        freeCompilerArgs.add("-Xdebug")
    }
}

Be warned that this should only be used during debugging, as this can cause memory leak warnings. What this means is that you have to comment this part out of your build.gradle unless you're actively running the debugger. Here's the site for more info: https://kotlinlang.org/docs/gradle-compiler-options.html

There's also a shorter way of defining this if you're using Kotlin Gradle:

val compileKotlin: KotlinCompile by tasks
compileKotlin.compilerOptions {
    freeCompilerArgs.add("-Xdebug")
}
  • Did not worked for me, I tried using (with kotlin 1.8.10): tasks.withType { compilerOptions { freeCompilerArgs.add("-Xdebug") } } – slaviboy Aug 15 '23 at 21:47
1

TL;DR: Use -Xdebug (Note the d is lowercase) compiler option, but ensure it isn't used in production

The reason and previous workarounds for this issue have been explained very nicely in this comment in the corresponding issue. In short, retaining variables could lead to memory leaks in some specific cases, and so it was decided to clean them up as soon as they were not used.

The severity of memory leaks without workarounds is much higher than miserable debuggability with workaround. ... Unfortunately, there is no way to preserve the values of the variables and avoid memory leaks. Thus, the sollution will come in some sort of compiler switch, which disables the bug fix.

With Kotlin 1.8 this exact compiler option has been added: -Xdebug.

Example for enabling this in maven (a better way could be to use maven profiles to ensure this isn't used in prod):

<plugin>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-maven-plugin</artifactId>
    <configuration>
        <args>
            <!--  Disables "x was optimized out" behaviour while debugging coroutines. Do NOT use in prod! -->
            <arg>-Xdebug</arg>
        </args>
    </configuration>
</plugin>

As this essentially disables the fix for possible memory leaks, this should not be used in production. As the official docs warn:

Never use this flag in production: -Xdebug can cause memory leaks.

aksh1618
  • 2,245
  • 18
  • 37