QoderCN Jetbrains插件存在EDT反模式

一、卡死的直接表现

EDT(AWT-EventQueue-0)被挂起,拿不到读锁(read permit)。 它的完整栈(文件第 1–53 行)自上而下是:

EDT → SuvorovProgress.dispatchEventsUntilComputationCompletes   ← EDT 被挂起后进入的模态事件循环
    → RunSuspend.await
    → NestedLocksThreadingSupport.acquireReadPermit             ← 卡在这里:等 read permit
    → ReadAction.compute
    → com.alibabacloud.intellij.cosy.core.lsp.LanguageClientImpl.lambda$pushCustomCommand$22  ← 触发点

也就是说:阿里云通义灵码(Cosy)插件的 LSP 客户端 LanguageClientImpl.pushCustomCommand(LanguageClientImpl.java:641)在 EDT 上同步调用了一个 ReadAction.compute(),而这个读锁始终拿不到,EDT 就此挂起 → 整个 UI 冻结。

二、为什么读锁拿不到?后台正在做 Maven 同步,锁被写方占住

整份 dump 里有 7 个 Java 线程 + 一批协程全部卡在 acquireReadPermit(worker-5/21/22/26/30/31 及 EDT)。在 IntelliJ 新锁机制(NestedLocksThreadingSupport + WriteIntentPermitImpl)下,一旦有线程声明了 write-intent 并排队等 write action permit,所有新的 read permit 都会被冻结,好让写方尽快拿到锁。

而此刻确实有写方在排队——来自 Maven 项目同步

线程/协程状态在做什么
协程 ProjectRootsSynchronizer (dump 第 9847 行附近)挂起等 acquireWriteActionPermitMavenProjectsManagerEx.checkOrInstallMavenWrapperregisterProjectRootWorkspaceModelImpl.updateWithRetry → 申请 write action 更新工作区模型
DefaultDispatcher-worker-19 (第 1115 行)持有 MavenSyncConsole@592102f5MavenWrapperDownloader.checkOrInstallMavenSyncConsole.startImportAbstractViewManager.configurePinnedContentinvokeAndWait 等 EDT
java (第 1020 行,唯一 BLOCKED)MavenSyncConsoleMaven 进程结束回调 terminateImportMavenSyncConsole.doFinish,锁被 worker-19 拿着

三、冻结闭环(死锁链)

① Maven 同步在后台跑 → 申请 write action 更新 workspace model
   → 声明 write-intent,冻结所有 read permit
        ↓
② 通义灵码 Cosy 在 EDT 上同步 ReadAction.compute(pushCustomCommand)
   → EDT 拿不到 read permit → 挂起进 SuvorovProgress 循环
        ↓
③ EDT 冻结 → 所有 invokeAndWait 等 EDT 的线程连锁卡死:
   • worker-19(持有 MavenSyncConsole 锁)卡在 invokeAndWait
   • 「Saving documents on frame deactivation」协程(文件末尾)卡在 invokeAndWait
   • 其它多个保存/刷新任务
        ↓
④ worker-19 不释放 MavenSyncConsole 锁 → Maven 进程结束回调(java) BLOCKED
   → Maven 同步无法收尾 → write action 队列无法推进
        ↓
⑤ 回到 ①,read permit 永不发放,EDT 永久挂起 → IDE 卡死

四、责任归属

  • 首要责任:阿里云通义灵码(Cosy)插件com.alibabacloud.intellij.cosy)。在 LSP 服务端→客户端的通知回调(pushCustomCommand)里同步在 EDT 上跑 ReadAction.compute 是反模式——LSP 回调本应在后台线程处理。它把一个原本只存在于后台的锁竞争,直接拉到了 EDT 上,成为压垮 UI 的最后一根稻草。同插件的 InlineEditActionProcessorCosyHeartbeatRunner 线程虽在场,但未参与锁竞争,属正常。
  • 触发场景:Maven 项目同步/导入正在进行,锁竞争本就激烈。
  • com.github.claudecodegui(Claude Code GUI 插件)的线程全部处于正常 wait/心跳状态,与本次冻结无关

五、建议

  1. 临时验证:禁用阿里云通义灵码(Cosy)插件后重做 Maven 同步,确认冻结消失。
  2. 若必须用该插件,避免在 Maven 同步进行时让其触发 LSP 回调;或向插件方反馈 LanguageClientImpl.pushCustomCommand 不应在 EDT 上同步执行 read action。
  3. Maven 同步本身是诱因,可留意项目规模/wrapper 下载是否异常拖长(本次 dump 里 worker-19 正卡在 MavenWrapperDownloader.checkOrInstall)。

展开
收起
gadfly3173 2026-07-28 11:06:48 32 分享 版权
0 条回答
写回答
取消 提交回答
问答分类:

通义灵码智能编码助手

还有其他疑问?
咨询AI助理