DebugProbes

Kotlin debug probes support.

Debug probes is a dynamic attach mechanism which installs multiple hooks into coroutines machinery. It slows down all coroutine-related code, but in return provides diagnostic information, including asynchronous stacktraces, coroutine dumps (similar to ThreadMXBean.dumpAllThreads and jstack) via DebugProbes.dumpCoroutines, and programmatic introspection of all alive coroutines. All introspecting methods throw IllegalStateException if debug probes were not installed.

Consistency guarantees

All snapshotting operations (e.g. dumpCoroutines) are weakly-consistent, meaning that they happen concurrently with coroutines progressing their own state. These operations are guaranteed to observe each coroutine's state exactly once, but the state is not guaranteed to be the most recent before the operation. In practice, it means that for snapshotting operations in progress, for each concurrent coroutine either the state prior to the operation or the state that was reached during the current operation is observed.

Overhead

  • Every created coroutine is stored in a concurrent hash map, and the hash map is looked up in and updated on each suspension and resumption.

  • If DebugProbes.enableCreationStackTraces is enabled, stack trace of the current thread is captured on each created coroutine that is a rough equivalent of throwing an exception per each created coroutine.

Internal machinery and classloading.

Under the hood, debug probes replace internal kotlin.coroutines.jvm.internal.DebugProbesKt class that has the following empty static methods:

  • probeCoroutineResumed that is invoked on every Continuation.resume.

  • probeCoroutineSuspended that is invoked on every continuation suspension.

  • probeCoroutineCreated that is invoked on every coroutine creation.

with a kotlinx-coroutines-specific class to keep track of all the coroutines machinery.

The new class is located in the kotlinx-coroutines-core module, meaning that all target application classes that use coroutines and suspend functions have to be loaded by the classloader in which kotlinx-coroutines-core classes are available.

Properties

Link copied to clipboard

Whether coroutine creation stack traces should be captured. When enabled, for each created coroutine a stack trace of the current thread is captured and attached to the coroutine. This option can be useful during local debug sessions, but is recommended to be disabled in production environments to avoid performance overhead of capturing real stacktraces.

Link copied to clipboard

Whether to ignore coroutines whose context is EmptyCoroutineContext.

Link copied to clipboard

Determines whether debug probes were installed.

Link copied to clipboard

Whether coroutine creation stack traces should be sanitized. Sanitization removes all frames from kotlinx.coroutines package except the first one and the last one to simplify diagnostic.

Functions

Link copied to clipboard
fun dumpCoroutines(out: PrintStream = System.out)

Dumps all active coroutines into the given output stream, providing a consistent snapshot of all existing coroutines at the moment of invocation. The output of this method is similar to jstack or a full thread dump. It can be used as the replacement to "Dump threads" action.

Link copied to clipboard

Returns all existing coroutines' info. The resulting collection represents a consistent snapshot of all existing coroutines at the moment of invocation.

Link copied to clipboard
fun install()

Installs a DebugProbes instead of no-op stdlib probes by redefining debug probes class using the same class loader as one loaded DebugProbes class.

Link copied to clipboard

Returns string representation of the coroutines job hierarchy with additional debug information. Hierarchy is printed from the job as a root transitively to all children.

Link copied to clipboard
fun printJob(job: Job, out: PrintStream = System.out)

Prints job hierarchy representation from jobToString to the given out.

Link copied to clipboard
fun printScope(scope: CoroutineScope, out: PrintStream = System.out)

Prints all coroutines launched within the given scope. Throws IllegalStateException if the scope has no a job in it.

Link copied to clipboard

Returns string representation of all coroutines launched within the given scope. Throws IllegalStateException if the scope has no a job in it.

Link copied to clipboard
fun uninstall()

Uninstall debug probes.

Link copied to clipboard
inline fun withDebugProbes(block: () -> Unit)

Invokes given block of code with installed debug probes and uninstall probes in the end.