• Home
Name Date Size #Lines LOC

..--

src/03-May-2024-870496

test/03-May-2024-1,3431,101

README.mdD03-May-20247.6 KiB168132

build.gradleD03-May-20241.3 KiB4033

README.md

1# Module kotlinx-coroutines-debug
2
3Debugging facilities for `kotlinx.coroutines` on JVM.
4
5### Overview
6
7This module provides a debug JVM agent that allows to track and trace existing coroutines.
8The main entry point to debug facilities is [DebugProbes] API.
9Call to [DebugProbes.install] installs debug agent via ByteBuddy and starts spying on coroutines when they are created, suspended and resumed.
10
11After that, you can use [DebugProbes.dumpCoroutines] to print all active (suspended or running) coroutines, including their state, creation and
12suspension stacktraces.
13Additionally, it is possible to process the list of such coroutines via [DebugProbes.dumpCoroutinesInfo] or dump isolated parts
14of coroutines hierarchy referenced by a [Job] or [CoroutineScope] instances using  [DebugProbes.printJob] and [DebugProbes.printScope] respectively.
15
16### Using in your project
17
18Add `kotlinx-coroutines-debug` to your project test dependencies:
19```
20dependencies {
21    testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-debug:1.3.1'
22}
23```
24
25### Using in unit tests
26
27For JUnit4 debug module provides special test rule, [CoroutinesTimeout], for installing debug probes
28and to dump coroutines on timeout to simplify tests debugging.
29
30Its usage is better demonstrated by the example (runnable code is [here](test/TestRuleExample.kt)):
31
32```kotlin
33class TestRuleExample {
34    @Rule
35    @JvmField
36    public val timeout = CoroutinesTimeout.seconds(1)
37
38    private suspend fun someFunctionDeepInTheStack() {
39        withContext(Dispatchers.IO) {
40            delay(Long.MAX_VALUE) // Hang method
41        }
42    }
43
44    @Test
45    fun hangingTest() = runBlocking {
46        val job = launch {
47            someFunctionDeepInTheStack()
48        }
49        job.join() // Join will hang
50    }
51}
52```
53
54After 1 second, test will fail with `TestTimeoutException` and all coroutines (`runBlocking` and `launch`) and their
55stacktraces will be dumped to the console.
56
57### Using as JVM agent
58
59It is possible to use this module as a standalone JVM agent to enable debug probes on the application startup.
60You can run your application with an additional argument: `-javaagent:kotlinx-coroutines-debug-1.3.1.jar`.
61Additionally, on Linux and Mac OS X you can use `kill -5 $pid` command in order to force your application to print all alive coroutines.
62
63
64### Example of usage
65
66Capabilities of this module can be demonstrated by the following example
67(runnable code is [here](test/Example.kt)):
68
69```kotlin
70suspend fun computeValue(): String = coroutineScope {
71    val one = async { computeOne() }
72    val two = async { computeTwo() }
73    combineResults(one, two)
74}
75
76suspend fun combineResults(one: Deferred<String>, two: Deferred<String>): String =
77    one.await() + two.await()
78
79suspend fun computeOne(): String {
80    delay(5000)
81    return "4"
82}
83
84suspend fun computeTwo(): String {
85    delay(5000)
86    return "2"
87}
88
89fun main() = runBlocking {
90    DebugProbes.install()
91    val deferred = async { computeValue() }
92    // Delay for some time
93    delay(1000)
94    // Dump running coroutines
95    DebugProbes.dumpCoroutines()
96    println("\nDumping only deferred")
97    DebugProbes.printJob(deferred)
98}
99```
100
101Printed result will be:
102
103```
104Coroutines dump 2018/11/12 21:44:02
105
106Coroutine "coroutine#2":DeferredCoroutine{Active}@289d1c02, state: SUSPENDED
107	at kotlinx.coroutines.DeferredCoroutine.await$suspendImpl(Builders.common.kt:99)
108	at ExampleKt.combineResults(Example.kt:11)
109	at ExampleKt$computeValue$2.invokeSuspend(Example.kt:7)
110	at ExampleKt$main$1$deferred$1.invokeSuspend(Example.kt:25)
111	(Coroutine creation stacktrace)
112	at kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)
113	at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:25)
114	at kotlinx.coroutines.BuildersKt.async$default(Unknown Source)
115	at ExampleKt$main$1.invokeSuspend(Example.kt:25)
116	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)
117	at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:233)
118	at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
119	at ExampleKt.main(Example.kt:23)
120	at ExampleKt.main(Example.kt)
121
122... More coroutines here ...
123
124Dumping only deferred
125"coroutine#2":DeferredCoroutine{Active}, continuation is SUSPENDED at line kotlinx.coroutines.DeferredCoroutine.await$suspendImpl(Builders.common.kt:99)
126			"coroutine#3":DeferredCoroutine{Active}, continuation is SUSPENDED at line ExampleKt.computeOne(Example.kt:14)
127		"coroutine#4":DeferredCoroutine{Active}, continuation is SUSPENDED at line ExampleKt.computeTwo(Example.kt:19)
128```
129
130### Status of the API
131
132API is purely experimental and it is not guaranteed that it won't be changed (while it is marked as `@ExperimentalCoroutinesApi`).
133Do not use this module in production environment and do not rely on the format of the data produced by [DebugProbes].
134
135### Debug agent and Android
136
137Unfortunately, Android runtime does not support Instrument API necessary for `kotlinx-coroutines-debug` to function, triggering `java.lang.NoClassDefFoundError: Failed resolution of: Ljava/lang/management/ManagementFactory;`.
138
139Nevertheless, it will be possible to support debug agent on Android as soon as [GradleAspectJ-Android](https://github.com/Archinamon/android-gradle-aspectj)  will support androin-gradle 3.3
140
141<!---
142Make an exception googlable
143java.lang.NoClassDefFoundError: Failed resolution of: Ljava/lang/management/ManagementFactory;
144        at kotlinx.coroutines.repackaged.net.bytebuddy.agent.ByteBuddyAgent$ProcessProvider$ForCurrentVm$ForLegacyVm.resolve(ByteBuddyAgent.java:1055)
145        at kotlinx.coroutines.repackaged.net.bytebuddy.agent.ByteBuddyAgent$ProcessProvider$ForCurrentVm.resolve(ByteBuddyAgent.java:1038)
146        at kotlinx.coroutines.repackaged.net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:374)
147        at kotlinx.coroutines.repackaged.net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:342)
148        at kotlinx.coroutines.repackaged.net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:328)
149        at kotlinx.coroutines.debug.internal.DebugProbesImpl.install(DebugProbesImpl.kt:39)
150        at kotlinx.coroutines.debug.DebugProbes.install(DebugProbes.kt:49)
151-->
152
153<!--- MODULE kotlinx-coroutines-core -->
154<!--- INDEX kotlinx.coroutines -->
155[Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html
156[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html
157<!--- MODULE kotlinx-coroutines-debug -->
158<!--- INDEX kotlinx.coroutines.debug -->
159[DebugProbes]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/index.html
160[DebugProbes.install]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/install.html
161[DebugProbes.dumpCoroutines]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/dump-coroutines.html
162[DebugProbes.dumpCoroutinesInfo]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/dump-coroutines-info.html
163[DebugProbes.printJob]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/print-job.html
164[DebugProbes.printScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/print-scope.html
165<!--- INDEX kotlinx.coroutines.debug.junit4 -->
166[CoroutinesTimeout]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug.junit4/-coroutines-timeout/index.html
167<!--- END -->
168