Durgan McBroom
07/03/2025, 8:35 AMMyCustomType to be garbage collected immediately after callThis completes (as happens without coroutines), however this does not happen.
class MyCustomType(val str: String)
suspend fun callThis() {
val type = MyCustomType("Test")
delay(100)
println(type.str)
}
suspend fun secondCall() {
delay(100)
}
@Test
fun `Testing coroutines`() {
runBlocking {
callThis()
secondCall()
}
}
Looking at the IntelliJ Memory profiler, the object is not removed until after secondCall . Im wondering why this memory needs to persist into the execution of the parent function? The value does not get garbage collected until after the next suspend call or after the runBlocking block has finished. In a scenario where a suspending function like this uses a lot of memory across coroutine boundary and then passes execution to a blocking program (still inside runBlocking) I could see a memory leak being caused, though I might be missing something.Youssef Shoaib [MOD]
07/03/2025, 9:09 AMsuspend, the JIT realizes that type never escapes its context, and hence removes it immediately, while with delay, the object does get stored somewhere (namely in the state machine for callThis), and hence such an optimization doesn't happen immediately. This shouldn't affect anything at all thoughYoussef Shoaib [MOD]
07/03/2025, 11:57 AMcallThis state machine instance between callThis and right before secondCall. This would only apply basically if callThis was inlined.
Also, that issue is solved, and I'm pretty sure I've observed correct behaviour in this circumstance in my experiments.ephemient
07/03/2025, 12:01 PMephemient
07/03/2025, 12:05 PMephemient
07/03/2025, 12:10 PMDurgan McBroom
07/03/2025, 6:17 PMprintln method in this example:
@Test
fun `Late night test`() {
runBlocking {
callThis()
System.gc()
println("Here") // Object still in memory
}
}
Is this what you meant?Durgan McBroom
07/03/2025, 6:21 PMDurgan McBroom
07/03/2025, 6:35 PM