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

为何非根非Supervisor协程的异常处理器能捕获异常?

Kotlin协程异常处理:为什么CEH2捕获了异常而非CEH1?

核心规则回顾

先明确Kotlin协程异常传播的关键逻辑:

  • 普通Job(如coroutineScope创建):子协程抛出异常时,会立即取消父Job及所有兄弟协程,异常持续向上传播,子协程的CoroutineExceptionHandler(CEH)会被忽略。
  • SupervisorJob(如supervisorScope创建):子协程抛出异常时,仅取消该子协程自身,不会影响父Job或其他兄弟协程。若子协程无CEH,异常不会传播给父SupervisorJob,而是直接传递给全局异常处理器;若父SupervisorJob有CEH,则调用自身CEH。
  • CEH生效条件:仅在根协程或异常传播路径中第一个拥有CEH的协程中生效,前提是该协程的父Job未拦截异常。

你的测试用例分析

不管是test还是test2,异常最终被CEH2捕获,原因如下:

  1. 异常传播路径:
    最内层协程抛出异常后,经过多层coroutineScope(普通Job)时,会持续向上传播——因为普通Job会将子协程异常传递给父协程。
  2. 遇到SupervisorJob后的处理:
    异常到达第一个supervisorScope(无CEH)时,由于该SupervisorJob没有自己的CEH,且它的父Job是launch(CEH2)的普通Job,异常会继续向上传递给launch(CEH2)。
  3. CEH2触发的原因:
    launch(CEH2)是异常传播路径中第一个携带CEH的协程,因此它的CEH会被调用,异常处理在此终止,不会继续传播到launch(CEH1)。

纠正你对官方文档的误解

官方文档中「子协程的CEH永远不会被使用」的前提是:父协程为普通Job,此时异常会被父协程接收并继续向上传播,子协程的CEH被跳过。但如果异常传播到一个携带CEH的协程,且该协程的父Job未拦截异常(如你的launch(CEH2)),则该CEH会被触发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 10:06:46