Intellij插件之调试停止生命周期

调试会话的创建

  1. 调试会话的创建由 XDebuggerManager.startSessionAndShowTab 接口创建,返回一个类型为 XDebugSession 的实例。它会在 Debug 窗口创建一个调试会话。XDebugSession 是一个接口,具体实现类型为 XDebugSessionImpl。

    image-20240609000255650

  2. 创建对应的 XDebugProcess 后广播 XDebuggerManagerListener 监听的 processStarted 事件。

    image-20240609000229263

  3. showToolWindowOnSuspendOnly 属性决定了调试会话的展示时机,true 则断点命中时展示,false 则默认展示。

  4. 之后就是广播 processHandler#startNotified 事件。再之后就是通过 XDebugProcessStarter 创建 XDebugProcess,一个 XDdebugProcess 绑定一个 XDebugSession。

  5. XDebugSession 初始化,初始化时对 XDebugProcess 中的 processHandler 添加了一个监听,当 processHandler 触发了 processTerminated 事件将会被广播回调。

    image-20240609084146084

调试停止

调试会话由 XDebugSession 管理,而 XDebugSession 会话绑定了一个 XDebugProcess,XDebugProcess 绑定一个 processHandler,所以当 processHandler 销毁时 XDebugSession 也就销毁了。

调试会话默认是不会自行关闭的,它可以由用户自己关闭,通过 UI 页面的入口:

image-20240609091512012

停止调试原理:

  1. 首先拿到当前运行所有的 RunContentDescriptor,然后遍历循环构造 HandlerItem 节点

    image-20240609092222568

  2. HandlerItem 节点有个 stop 接口,点击每个节点都会触发,最后通过 ExecutionManagerImpl.stopProcess(descriptor) 销毁

    image-20240609091747744

  3. 从代码实现逻辑可以看到最终销毁的就是一个 processHandler,而调试会话中的 XDebugProcess 绑定的是一个 DefaultDebugProcessHandler

    image-20240609092445107

    image-20240609093021469

    image-20240609092938117

    image-20240609092957033

    广播 ProcessListener 监听的 processWillTerminate 和 processTerminated 事件

    image-20240609093052758

    image-20240609093309788

    回过头来我们再看 XDebugSession 中对 XDebugProcess 中 processHandler 的注册监听:

    image-20240609092613978

    image-20240609092646141

    stopImpl 中做的事情主要是 XDebugProcess的一个 stopAsync 异步回调方法,默认不做任何事情,由用户自己编写的 XDebugProcess 实现去实现此方法,onSuccess 后触发 processStopped 方法:

    image-20240609093724222

    从上面可以看到首先将会发布 XDebuggerManager.TOPIC 的事件订阅,然后再从调试会话管理中移除 XDebugSesion,再然后广播 XDebugSessionListener#sessionStopped 事件,最后把所有 XDebugSessionListener 监听移除。

    调试会话各个监听器停止顺序

    所以通过以上分析我们有了以下结论,Intellij 调试会话停止时隔个监听广播销毁的顺序为:

    1. processHandler 中的 ProcessListener 监听器

    2. XDebugProcess#stop 方法

    3. XDebuggerManagerListener#processStopped 方法

    4. XDebugSession 从调试会话管理(XDebuggerManager)中移除

    5. XDebugSessionListener#sessionStopped 方法

    6. XDebugSessionListener 监听移除