kotlin协程代码生成-5.Debug(译)

kotlin协程代码生成翻译文章系列,翻译自 coroutineCodegenUtil.kt

Debug

调试协程并不像调试常规代码那样直观。例如,由于挂起调用可能会暂停,甚至简单的调试事件,如"步进",都需要代码生成器和调试器的支持才能实现。另一个例子是从协程中抛出异常,这可能导致不同的堆栈跟踪,取决于协程是否已经暂停并且然后恢复,或者暂停是否从未发生过。如果协程已经暂停并且然后恢复,堆栈跟踪甚至可能没有用户代码,只有库代码,使得调试变得非常困难。

本节将解释代码生成器如何提供调试器所需的信息。

Step-over

在协程代码生成中,历史上第一个的调试支持是"步进"功能。该调用会返回一个值或COROUTINE_SUSPENDED标记。因此,状态机会检查结果,并继续执行或返回该标记。因此,状态机构建器会生成两个执行路径:直接调用和挂起-恢复。如果调用返回一个值,那么"步进"操作会像平常一样运行。然而,如果我们想要支持挂起-恢复路径,则需要代码生成器和调试器的一些技巧。

首先,代码生成器在返回COROUTINE_SUSPENDED标记之前会放置额外的LINENUMBER指令。这样,当用户按下"步进"按钮时,调试器会在这个LINENUMBER处设置断点,并在执行到达下一行(在直接路径的情况下)或断点时移除它。这个虚构的LINENUMBER的行号是调用者标头的行号。我们选择了这个数字,因为我们需要行号在函数之间不同(可能有多个挂起调用,等待"步进"完成),而且不干扰用户代码。

当协程恢复时,断点会再次触发,因为代码生成器在函数开始处生成另一个LINENUMBER

总而言之,代码生成器在挂起-恢复路径中生成了N+1个虚构的LINENUMBER指令,因此调试器可以在行号上放置断点,并使用一个断点模拟"步进",该断点被触发两次。

Debug Metadata

The continuation-passing-style 解释了当我们恢复一个协程时,它的调用者变成了BaseContinuationImpl.resumeWith。然而,用户希望看到调用挂起协程的协程。幸运的是,可以通过completion链获得关于调用者的信息。使用该链构造的堆栈跟踪称为异步堆栈跟踪。

然而,首先,代码生成器应提供这些信息。为此,每个继续类都有一个@kotlin.coroutines.jvm.internal.DebugMetadata注解,其中包含以下字段:

  1. 源文件、类名和方法名,以及行号,用于生成异步堆栈跟踪元素。
  2. 一个行号数组,将label值映射到挂起点行号。
  3. 从溢出变量到本地变量的映射,调试器用于显示变量的值。

调试器和kotlinx.coroutines都使用调试元数据生成异步堆栈跟踪。

继续类的toString方法使用调试元数据显示协程挂起的位置。

请注意,尾调用优化会删除继续类。因此,异步堆栈跟踪中存在间隙。此外,只存储挂起点的行号;因此,行号并不总是准确的。

Probes

kotlin.coroutines.jvm.internal 包含一些探测函数,由调试器替换以显示当前协程(在广义上)及其状态:挂起或运行。

  1. probeCoroutineCreatecreateCoroutine 函数中被调用。
  2. probeCoroutineResumedBaseContinuationImpl.resumeWith 函数中被调用。
  3. 如果 suspendCoroutineUninterceptedOrReturn 返回 COROUTINE_SUSPENDED,则代码生成器生成 probeCoroutineSuspended 调用。
相关推荐
_Shirley3 小时前
鸿蒙设置app更新跳转华为市场
android·华为·kotlin·harmonyos·鸿蒙
小白学大数据13 小时前
高级技术文章:使用 Kotlin 和 Unirest 构建高效的 Facebook 图像爬虫
爬虫·数据分析·kotlin
guitarjoy21 小时前
Kotlin - 协程结构化并发Structured Concurrency
kotlin·协程·coroutinescope·结构化同步
zhangphil1 天前
Android使用PorterDuffXfermode模式PorterDuff.Mode.SRC_OUT橡皮擦实现“刮刮乐”效果,Kotlin(2)
android·kotlin
居居飒2 天前
Android学习(四)-Kotlin编程语言-for循环
android·学习·kotlin
刘争Stanley3 天前
如何高效调试复杂布局?Layout Inspector 的 Toggle Deep Inspect 完全解析
android·kotlin·android 15·黑屏闪屏白屏
sickworm陈浩3 天前
Java 转 Kotlin 系列:究竟该不该用 lateinit?
android·kotlin
droidHZ4 天前
Compose Multiplatform 之旅—声明式UI
android·kotlin
zhangphil4 天前
Android基于Path的addRoundRect,Canvas剪切clipPath简洁的圆角矩形实现,Kotlin(1)
android·kotlin
alexhilton7 天前
Android技巧:学习使用GridLayout
android·kotlin·android jetpack