You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用coroutineScope时出现Kotlin协程内存泄漏问题的复现

Kotlin协程coroutineScope导致内存泄漏的原因与修复

问题原因

你碰到的内存泄漏,本质是冗余的coroutineScope + async写法引发的残留引用:

  • 你写的io函数用coroutineScope包裹async(Dispatchers.IO)再await,这种组合完全没必要——async + await在coroutineScope里的行为和withContext(Dispatchers.IO)完全一致,但前者会额外生成一个Deferred对象。
  • 由于io是inline函数,生成大字符串的代码会被内联到async的lambda中,coroutineScope创建的作用域会跟踪这个子协程。
  • 当await完成后,虽然你已经拿到结果返回,但coroutineScope的作用域对象会被外层runBlocking的协程上下文持有(因为Thread.sleep阻塞了主线程,导致runBlocking协程一直处于活跃状态),这个作用域保留着对Deferred的引用,间接持有了大字符串,导致它无法被GC回收。

修复方法

把冗余的coroutineScope + async替换成withContext,既保留切换IO线程的能力,又避免多余的对象引用:

修复后的io函数

suspend inline fun <R> io(crossinline body: suspend () -> R): R =
    withContext(Dispatchers.IO) { body() }

直接简化runGaqlRequest(如果不需要复用io函数)

suspend fun runGaqlRequest(): List<String> = withContext(Dispatchers.IO) {
    listOf("A".repeat(300_000_000))
}

补充说明

移除coroutineScope后正常的原因:直接返回大字符串时,没有额外的协程作用域或Deferred对象持有它的引用,当myReport将原列表映射为新列表后,原大字符串失去所有可达引用,自然会被垃圾回收。

内容的提问来源于stack exchange,提问作者Jelmer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 21:08:22