macOS 应用强制退出后无法再次启动:根因分析、排查方法与无重启恢复方
2026/6/9 1:41:47 网站建设 项目流程

记录时间:2026-06-08
实测环境:macOS 26.5(Build 25F71,Apple Silicon)
涉及应用:IntelliJ IDEA、Codex、CC Switch
本次实测 IDEA 版本:IntelliJ IDEA 2026.1.2
本次实测 JetBrains Runtime:JBR 25.0.2
本次实测 Codex 版本:26.602.40724

一、问题现象

某些 macOS 桌面应用原本可以正常运行,卡死后被强制退出,随后出现以下现象:

  1. 再次点击 Dock、Launchpad 或“应用程序”中的图标,没有任何可见反应。
  2. 执行open -a "应用名称",命令很快返回,但应用窗口没有出现。
  3. 杀掉应用相关进程后仍无法启动。
  4. 重新安装应用通常不是必需的。
  5. 重启 Mac 后应用又可以正常启动。
  6. 问题不是固定发生在一个应用上,IntelliJ IDEA、Codex、CC Switch 都曾出现过。

这类现象很容易被误判为:

  • App 文件损坏;
  • 应用缓存损坏;
  • 应用锁文件没有删除;
  • Java 进程没有杀干净;
  • Dock 或 LaunchServices 缓存异常。

本次现场排查表明,实际问题至少分成两层:

  1. 应用为什么会先卡死
  2. 强制退出后,为什么新进程无法完成启动

这两层问题必须分开分析。


二、结论摘要

2.1 IDEA 最初卡死的直接原因

IDEA 的多份 freeze thread dump 显示:

  • UI 主线程AWT-EventQueue-0一直等待Java2D Disposer
  • Java2D Disposer又在等待 macOS Metal 渲染队列;
  • 关键调用包括:
sun.java2d.metal.MTLRenderQueue.flushAndInvokeNow sun.java2d.Disposer FontStrikeDisposer StrikeCache.disposeStrike

这说明 IDEA 最初的卡死发生在JetBrains Runtime 的 Java2D Metal 渲染路径

本次对 IDEA 增加了下面的用户级 JVM 参数:

-Dsun.java2d.metal=false

该参数关闭 Java2D 的 Metal 渲染后端,改用其他渲染路径,用来规避这类 Metal 渲染线程卡死。

2.2 强制退出后无法再次启动的直接原因

IDEA 被强制退出后,新启动出来的 IDEA 进程并不是一个正常 JVM,而只是一个很小的启动器空壳。

对启动器采样后发现,线程卡在:

JNI_CreateJavaVM LoadJavaVM dlopen dyld4::Loader::mapSegments fcntl

也就是说:

新 IDEA 还没有创建 JVM,也没有读取 IDEA 的锁文件、缓存或项目配置,就已经卡在 macOS 动态库装载和系统策略校验阶段。

与此同时,macOS 的syspolicyd日志持续出现:

UNIX error exception: 24 Failed to generate SecStaticCode ... error: 100024 failed to call driver: 0x3

其中 Unixerrno 24的含义是:

EMFILE: Too many open files

进一步检查syspolicyd的文件描述符时发现:

  • 该进程打开了约 2575 个文件句柄;
  • 其中约 2536 个句柄都重复指向:
/Applications/Codex.app/Contents/MacOS/Codex

因此,本次“强退后再次点击没有反应”的直接原因是:

macOS 的系统策略服务syspolicyd出现了文件描述符泄漏或异常积压,无法继续完成新可执行文件和动态库的代码签名、来源及安全策略检查。新应用虽然被 LaunchServices 创建了进程,但进程卡在非常早期的加载阶段。

2.3 为什么重启 Mac 一定有效

重启会同时完成下面几件事:

  1. 结束异常的syspolicyd
  2. 清空它泄漏或积压的文件描述符;
  3. 清理 LaunchServices、RunningBoard 中记录的半启动应用状态;
  4. 清除应用启动器空壳;
  5. 重新初始化动态链接和代码校验相关系统服务。

所以重启能恢复,但这并不代表 App 文件已经被重装修复。


三、IDEA、Codex、CC Switch 三个问题是否有关

3.1 有关联,但不是“IDEA 导致其他两个应用坏了”

更准确的关系是:

IDEA、Codex、CC Switch │ ├── 各自可能有不同的初始卡死原因 │ └── 强制退出后重新启动时,都要经过相同的 macOS 启动基础设施 │ ├── LaunchServices ├── RunningBoard ├── dyld ├── amfid └── syspolicyd

因此:

  • IDEA 的 Metal 渲染卡死,只解释 IDEA 为什么先失去响应;
  • 它不能解释 Codex 和 CC Switch 以前为什么也出现过相同症状;
  • 三个应用共同出现“强退后无法再次启动、重启后恢复”,说明它们很可能共享了同一类系统启动层故障;
  • 本次现场已经实证syspolicyd发生文件描述符耗尽;
  • 以前 Codex、CC Switch 出现问题时没有保留当时日志,因此只能判断为高度可能属于同一故障类型,不能百分之百断言当时也是同一个 PID、同一个泄漏目标。

3.2 Codex 在本次故障中的角色

本次重启syspolicyd后,新的syspolicyd很快又出现大量重复打开 Codex 主程序的文件句柄。

这说明当前环境中:

Codex 相关的可执行文件校验或其子进程来源校验,是触发、放大或暴露syspolicyd文件描述符泄漏的重要条件。

但是,不能仅凭这个现象就断言“Codex 应用逻辑主动泄漏了文件”。

原因是这些句柄属于 root 用户运行的syspolicyd,不是 Codex 自己的句柄。更可能的情况是:

  1. Codex 或 Codex 启动的子进程频繁触发 macOS provenance/code-signing 检查;
  2. macOS 26.5 的syspolicyd在处理这些请求时没有正确关闭 Codex 主程序句柄;
  3. 请求积累后,syspolicyd达到自己的文件描述符上限;
  4. 后续任何应用的代码校验或动态库装载都可能被拖死。

3.3 Codex 是否被本地命令改坏

本次从 OpenAI 官方地址重新下载了 Codex DMG,并做了只读对照:

  • 官方 DMG 校验通过;
  • 官方 DMG 内的 Codex 版本也是26.602.40724
  • 官方包中的 Codex 主程序与/Applications/Codex.app主程序 SHA-256 完全一致;
  • 官方包和已安装副本在当前 macOS 上执行严格codesign --verify时表现一致。

所以:

当前/Applications/Codex.app不是被用户历史命令单独改坏的副本。重新安装完全相同的官方版本,未必能解决当前syspolicyd问题。

更值得关注的是:

  • macOS 26.5;
  • Codex 26.602.40724;
  • 系统策略服务syspolicyd
  • Codex 及其子进程触发的 provenance/code-signing 校验;
  • 这几者之间的组合行为。

3.4 CC Switch 的情况

历史中执行过:

codesign--force--deep--sign- /Applications/CC\Switch.app xattr-cr/Applications/CC\Switch.app

它们的影响是:

  • codesign --sign -会把 CC Switch 改成 ad-hoc 签名;
  • --deep会递归处理应用包中的嵌套组件;
  • xattr -cr会递归移除隔离、来源和其他扩展属性;
  • 这些修改只直接作用于 CC Switch,不会直接修改 IDEA 或 Codex。

因此:

  • 它们不能解释 IDEA 和 Codex 也出现同类问题;
  • 它们可能让 CC Switch 自己的签名、更新和系统来源校验变得更复杂;
  • 后续不建议把“重新签名整个 App”作为常规修复手段。

四、历史命令与本次故障的关系

历史操作是否是本次根因说明
git commitgit remotegit push与 macOS 应用启动链路无关
设置或取消HTTP_PROXYHTTPS_PROXY基本无关只影响网络请求和 Homebrew 下载,不会造成本地 JVM 卡在dlopen/fcntl
Homebrew 下载 CC Switch 失败只是代理端口配置错误
npm run dev与 IDEA 主程序装载无直接关系
pkill -f "IntelliJ IDEA"是触发动作,不是根因强制终止了应用,但没有修复已经异常的系统策略服务
pkill -f "fsnotifier"不是根因只影响 JetBrains 文件监控子进程
open -a "IntelliJ IDEA"不是根因只是提交启动请求;系统服务异常时它可能无错误返回
对 CC Switch 执行codesign --force --deep --sign -只影响 CC Switch可能带来 CC Switch 自身签名和更新风险,但不会直接改坏 IDEA 或 Codex
对 CC Switch 执行xattr -cr只影响 CC Switch移除该 App 的扩展属性,不是全局修复

五、为什么open -a没报错,但应用就是不出来

open -a的主要职责是把启动请求交给 LaunchServices。

它不是在当前终端中同步等待应用完成所有初始化。

本次系统日志显示:

  1. RunningBoard 接受了 IDEA 启动请求;
  2. 系统成功创建了 IDEA PID;
  3. RunningBoard 把它标记为running-active
  4. 但 IDEA 启动器在创建 JVM 时卡住;
  5. 因为系统已经认为 Bundle ID 对应的应用正在运行,后续点击图标可能只会尝试激活这个半启动进程;
  6. 所以用户看到的效果就是“点击完全没反应”。

这类进程通常具有以下特点:

  • PID 存在;
  • CPU 很低;
  • RSS 内存只有几 MB;
  • 没有完整 JVM 线程;
  • 没有打开 IDEA 的配置、缓存、项目文件和本地端口;
  • sample显示卡在dlopendyldfcntlcodesign或安全策略相关调用。

六、下次遇到问题时的 5 分钟无重启恢复流程

以下流程优先恢复系统,不删除应用数据,也不重装应用。

第 0 步:保存其他应用中的工作

重启syspolicyd通常不会关闭普通应用,但执行任何系统级恢复前,都建议先保存正在编辑的文件。

如果 Codex 正在运行,并且不是用 Codex 自己排查问题,建议先正常退出 Codex,避免它继续创建子进程并触发新的校验请求。

第 1 步:确认目标应用有没有留下空壳进程

IDEA:

ps-axopid,ppid,%cpu,%mem,rss,state,lstart,command\|grep-E'/Applications/IntelliJ IDEA.app/Contents/MacOS/idea|fsnotifier'\|grep-vgrep

Codex:

ps-axopid,ppid,%cpu,%mem,rss,state,lstart,command\|grep-E'/Applications/Codex.app/Contents/MacOS/Codex'\|grep-vgrep

CC Switch:

ps-axopid,ppid,%cpu,%mem,rss,state,lstart,command\|grep-Ei'CC Switch|cc-switch|ccswitch'\|grep-vgrep

如果目标应用的主进程存在,但内存很小、长时间没有窗口,可以先记录 PID。

第 2 步:确认syspolicyd是否异常

查看 CPU:

ps-axopid,ppid,user,%cpu,%mem,state,lstart,command\|grep'[s]yspolicyd'

正常情况下,syspolicyd不应该长时间占用很高 CPU。

检查最近错误:

log show--last10m--stylecompact\--predicate'process == "syspolicyd"'\|grep-E'UNIX error exception: 24|Failed to generate SecStaticCode|failed to call driver'

如果反复看到:

UNIX error exception: 24

基本可以确认syspolicyd已达到文件描述符上限。

检查打开文件总数:

sudolsof-nP-p"$(pgrep-xsyspolicyd)"|wc-l

检查是否大量重复打开某个 App:

sudolsof-nP-p"$(pgrep-xsyspolicyd)"\|awk'NR > 1 { name = $9 for (i = 10; i <= NF; i++) name = name " " $i count[name]++ } END { for (name in count) print count[name], name }'\|sort-nr\|head-n20

如果前几名出现数百或数千次相同的 App 主程序,说明已经抓到非常强的文件描述符泄漏证据。

第 3 步:结束目标应用的半启动空壳

先使用普通TERM

kill<目标应用PID>

等待两秒后确认:

ps-p<目标应用PID>

只有进程仍然存在时,才使用:

kill-9<目标应用PID>

注意:

  • 不要对不确定的 PID 直接执行kill -9
  • 如果应用已经完整启动并可能有未保存数据,应先正常退出;
  • 本次 IDEA PID21412已确认没有创建 JVM,因此结束它不会丢失项目编辑状态。

第 4 步:只重启syspolicyd

在终端执行:

sudokillallsyspolicyd

输入 Mac 管理员密码。

syspolicyd是 launchd 管理的系统服务。终止旧进程后,macOS 会自动启动一个新的实例。

检查 PID 是否变化:

pgrep-lfsyspolicyd

本次实测中:

  • 旧 PID 为495
  • 重启后变成91960
  • 再次重启后又变成87102

PID 变化说明系统服务已经被重新拉起。

不要使用下面这条命令作为首选:

sudolaunchctl kickstart-ksystem/com.apple.security.syspolicy

本次在开启 SIP 的正常系统中,该命令返回:

Operation not permitted while System Integrity Protection is engaged

没有必要为了这件事关闭 SIP。

第 5 步:重新启动应用

IDEA:

open-na"IntelliJ IDEA"

Codex:

open-na"Codex"

CC Switch:

open-na"CC Switch"

如果应用本来就支持单实例,也可以使用:

open-a"应用名称"

在已经清理空壳进程的前提下,-n可以明确要求 LaunchServices 创建新实例。

第 6 步:验证不是“又启动了一个空壳”

以 IDEA 为例:

ps-axopid,ppid,%cpu,%mem,rss,state,lstart,command\|grep'/Applications/IntelliJ IDEA.app/Contents/MacOS/idea'\|grep-vgrep

完整 IDEA JVM 通常会占用数百 MB 到数 GB 内存,而不是几 MB。

继续确认:

ps-axopid,ppid,command\|grep-E'fsnotifier|jetbrainsd'\|grep-vgrep

查看最新 IDEA 日志:

tail-n100"$HOME/Library/Logs/JetBrains/IntelliJIdea2026.1/idea.log"

看到插件加载、项目加载、索引等日志,说明 IDEA 已经越过启动器和 JVM 创建阶段。


七、IDEA 专项修复:关闭 Java2D Metal

7.1 推荐方法

IDEA 能启动时,在菜单中打开:

Help -> Edit Custom VM Options

加入:

-Dsun.java2d.metal=false

然后完全退出并重新启动 IDEA。

7.2 IDEA 无法启动时手动修改

本次 IDEA 2026.1 的用户级 VM 参数文件是:

~/Library/Application Support/JetBrains/IntelliJIdea2026.1/idea.vmoptions

查看文件:

cat"$HOME/Library/Application Support/JetBrains/IntelliJIdea2026.1/idea.vmoptions"

避免重复添加:

VM_OPTIONS="$HOME/Library/Application Support/JetBrains/IntelliJIdea2026.1/idea.vmoptions"grep-qxF--'-Dsun.java2d.metal=false'"$VM_OPTIONS"\||printf'%s\n''-Dsun.java2d.metal=false'>>"$VM_OPTIONS"

本次最终文件内容为:

# custom IntelliJ IDEA VM options (expand/override 'bin/idea.vmoptions') -Dsun.java2d.metal=false

7.3 如何确认参数已经生效

执行:

grep-F--'-Dsun.java2d.metal=false'\"$HOME/Library/Logs/JetBrains/IntelliJIdea2026.1/idea.log"\|tail

本次新启动日志的JVM options同时出现:

-Dsun.java2d.metal=true -Dsun.java2d.metal=false

后出现的用户自定义参数会覆盖前面的默认值,因此最终使用false

7.4 不要修改 App 包里的默认 VM 参数

不要直接编辑:

/Applications/IntelliJ IDEA.app/Contents/bin/idea.vmoptions

原因:

  1. 更新 IDEA 时可能被覆盖;
  2. 修改 App Bundle 内容可能破坏代码签名;
  3. JetBrains 提供了用户级 Custom VM Options 机制,应该优先使用它。

JetBrains 官方说明:

  • Tuning the IDE

八、完整深度排查流程

当快速恢复流程无效时,按以下顺序定位。

8.1 先判断应用处在哪个启动阶段

情况 A:完全没有 PID

可能原因:

  • LaunchServices 没有真正创建进程;
  • App Bundle 注册异常;
  • 路径或 Bundle ID 不正确;
  • 系统安全策略直接拒绝启动。

检查:

open-a"应用名称"echo$?

然后查看:

log show--last5m--stylecompact\--predicate'process == "launchservicesd" OR process == "runningboardd" OR process == "amfid"'
情况 B:PID 存在,但内存只有几 MB

这通常是启动器空壳。

执行采样:

sample<PID>51-file"$HOME/Desktop/app-launch.sample.txt"

重点搜索:

grep-E'JNI_CreateJavaVM|dlopen|dyld|fcntl|codesign|syspolicy'\"$HOME/Desktop/app-launch.sample.txt"

如果卡在dlopen/dyld/fcntl,优先排查syspolicyd,不要先删除应用缓存。

情况 C:完整 JVM 已经启动,但没有窗口

可能原因:

  • 窗口状态恢复异常;
  • 插件卡死;
  • 项目加载卡死;
  • 单实例锁或本地端口异常;
  • UI 线程死锁;
  • 图形渲染问题。

此时再检查:

jcmd<IDEA_PID>Thread.print-l

如果jcmd自己也长时间卡住,要重新考虑底层系统服务是否异常。

情况 D:完整 JVM 已启动,而且 CPU 或内存异常

重点分析:

  • IDEA freeze thread dump;
  • GC;
  • 插件;
  • 索引;
  • 文件系统监听;
  • Java2D、Metal 或 Skia 渲染;
  • 外部构建进程。

8.2 检查 IDEA freeze dump

目录:

~/Library/Logs/JetBrains/IntelliJIdea2026.1/threadDumps-freeze-*

查找 Metal 渲染调用:

grep-R-n-E'MTLRenderQueue|Java2D Disposer|StrikeCache|FontStrikeDisposer'\"$HOME/Library/Logs/JetBrains/IntelliJIdea2026.1"/threadDumps-freeze-*\|head-n100

本次的关键关系是:

AWT-EventQueue-0 waits for Java2D Disposer Java2D Disposer waits for MTLRenderQueue

这不是普通的项目索引慢,而是 UI 渲染链路阻塞。

8.3 检查 IDEA 自带 JBR 是否能独立启动

"/Applications/IntelliJ IDEA.app/Contents/jbr/Contents/Home/bin/java"-version

正常时应该很快输出版本。

本次在syspolicyd异常时,该命令超过 12 秒仍无输出;重启syspolicyd后立刻输出:

openjdk version "25.0.2" OpenJDK Runtime Environment JBR-25.0.2 OpenJDK 64-Bit Server VM JBR-25.0.2

这个对照可以证明:

  • JBR 文件本身并未损坏;
  • 卡住的是系统装载和校验链路;
  • 重装 IDEA 不是当时最有效的动作。

8.4 检查锁文件,但不要把锁文件当成默认根因

IDEA 常见文件:

~/Library/Application Support/JetBrains/IntelliJIdea2026.1/.lock ~/Library/Caches/JetBrains/IntelliJIdea2026.1/.port

只有满足下面条件时,才考虑删除:

  1. 已确认没有任何 IDEA 主进程;
  2. 已确认没有 JetBrains 后台组件仍在使用;
  3. 日志明确指向单实例锁或端口;
  4. 备份或记录了原文件。

本次 IDEA 启动器在打开这些文件之前就已经卡住,因此删除.lock.port不能解决本次根因。

8.5 检查系统内存压力

memory_pressure vm_stat

本次 Mac 有 64GB 内存,空闲充足,没有 swap、压缩和 pageout 压力,因此不是内存不足。

8.6 检查 App 签名时要谨慎解释结果

查看签名:

codesign-d--verbose=4"/Applications/应用名称.app"

验证:

codesign--verify--deep--strict--verbose=4"/Applications/应用名称.app"

查看 Gatekeeper:

spctl--statusspctl--assess--typeexecute--verbose=4"/Applications/应用名称.app"

注意:

  • codesign --verify失败不一定能单独证明本地文件被篡改;
  • 应与官方包做哈希和签名对照;
  • 本次官方 Codex DMG 与已安装 Codex 的主程序哈希相同;
  • 当前系统中spctl --status显示 assessments disabled,这不是本次文件描述符泄漏的直接原因,但会让签名问题更难判断;
  • 不要为了绕过提示长期关闭 Gatekeeper,更不要为了本问题关闭 SIP。

九、Codex 的长期处理建议

9.1 当前版本不建议单纯重复安装

本次官方 DMG 与已安装副本版本和主程序哈希一致。

因此,在仍然是26.602.40724的情况下,简单地“删除后重新安装同一个包”未必能改变syspolicyd的表现。

9.2 优先升级到后续 Codex 版本

当 OpenAI 发布新版本后:

  1. 正常退出 Codex;
  2. 安装新的官方版本;
  3. 不要自行对 Codex 执行codesign --force --deep --sign -
  4. 不要对 Codex 执行递归xattr -cr作为常规操作;
  5. 升级后观察syspolicyd是否还会大量重复打开 Codex 主程序。

查看当前版本:

/usr/libexec/PlistBuddy\-c'Print :CFBundleShortVersionString'\"/Applications/Codex.app/Contents/Info.plist"

OpenAI 官方 Codex App 文档:

  • Codex App

Apple Silicon 官方安装包:

  • Codex.dmg

9.3 如果问题复现,先退出 Codex 再重启syspolicyd

如果不是在 Codex 中排查,可先正常退出 Codex,然后执行:

sudokillallsyspolicyd

再启动目标应用。

这样可以避免重启后的syspolicyd立即继续接收大量来自 Codex 子进程的校验请求。

9.4 保存可提交给 OpenAI 或 Apple 的证据

复现后立即执行:

mkdir-p"$HOME/Desktop/app-launch-diagnosis"ps-axopid,ppid,user,%cpu,%mem,rss,state,lstart,command\>"$HOME/Desktop/app-launch-diagnosis/processes.txt"log show--last15m--stylecompact\--predicate'process == "syspolicyd" OR process == "amfid" OR process == "launchservicesd" OR process == "runningboardd"'\>"$HOME/Desktop/app-launch-diagnosis/system-launch.log"sudolsof-nP-p"$(pgrep-xsyspolicyd)"\>"$HOME/Desktop/app-launch-diagnosis/syspolicyd-lsof.txt"

如果目标应用留下空壳:

sample<目标应用PID>101\-file"$HOME/Desktop/app-launch-diagnosis/app-launch.sample.txt"

提交日志前应先检查其中是否包含:

  • 用户名;
  • 项目路径;
  • 本地文件名;
  • 网络地址;
  • Token;
  • 其他隐私信息。

十、CC Switch 的长期处理建议

10.1 不再把 ad-hoc 重签作为常规方案

下面这类命令只适合明确知道签名后果时使用:

codesign--force--deep--sign-"/Applications/CC Switch.app"

风险包括:

  • 改变原开发者签名;
  • 破坏自动更新校验;
  • 嵌套组件签名状态变化;
  • 与系统 provenance、Gatekeeper 记录不一致;
  • 后续难以判断到底是官方包问题还是本地修改问题。

10.2 出现同类现象时先检查系统层

如果 CC Switch 再次出现:

  1. 点击无反应;
  2. open -a "CC Switch"无明显报错;
  3. 重启 Mac 后恢复;

应先检查:

log show--last10m--stylecompact\--predicate'process == "syspolicyd"'\|grep-E'UNIX error exception: 24|Failed to generate SecStaticCode'

不要立刻再次重签整个 App。


十一、不要优先做的操作

11.1 不要反复点击图标或循环执行open -a

它不会修复系统策略服务,还可能产生更多半启动请求和日志噪声。

11.2 不要一上来就删除整个应用配置目录

例如不要直接删除:

~/Library/Application Support/JetBrains ~/Library/Caches/JetBrains ~/Library/Application Support/Codex

本次根因发生在应用读取这些目录之前,删除配置只会丢失设置,不能修复syspolicyd

11.3 不要默认删除.lock.port

只有日志和进程状态证明是单实例锁问题时才处理。

11.4 不要随意重建 LaunchServices 数据库

LaunchServices 只是把进程创建出来。本次真正阻塞发生在进程创建后的 JVM/动态库装载阶段。

11.5 不要关闭 SIP

本问题不需要关闭 SIP。

11.6 不要长期关闭 Gatekeeper

本次系统显示 Gatekeeper assessments disabled。虽然这不是syspolicyd泄漏的直接原因,但长期关闭会降低下载应用的安全校验能力,也会使签名排查失去重要参照。

11.7 不要把kill -9当作第一选择

先尝试正常退出或kill。只有进程不响应并且已确认无未保存状态时才使用kill -9


十二、本次实际执行的恢复步骤

本次没有重启 Mac,实际完成了以下操作:

  1. 确认 macOS 版本为 26.5,系统内存充足;
  2. 找到 IDEA 空壳进程 PID21412
  3. 使用lsof证明该进程没有打开 IDEA 配置、缓存和锁文件;
  4. 使用sample证明它卡在JNI_CreateJavaVM -> dlopen -> dyld -> fcntl
  5. 使用 IDEA freeze dump 证明原始 UI 卡死发生在 Java2D Metal 渲染链路;
  6. syspolicyd日志中确认errno 24
  7. 发现syspolicyd大量重复打开 Codex 主程序;
  8. 使用管理员权限终止旧syspolicyd,由 launchd 自动拉起新实例;
  9. 验证 IDEA 自带 JBR 的java -version恢复正常;
  10. 在用户级idea.vmoptions中加入:
-Dsun.java2d.metal=false
  1. 结束 IDEA 空壳进程;
  2. 再次重启syspolicyd
  3. 执行:
open-na"IntelliJ IDEA"
  1. IDEA 成功启动为完整 JVM;
  2. 新 IDEA PID 为18337,RSS 约 1.7GB;
  3. fsnotifierjetbrainsd均正常启动;
  4. IDEA 日志进入项目加载和索引阶段;
  5. IDEA 日志确认-Dsun.java2d.metal=false已生效。

十三、下次处理时的最短命令清单

确认目标应用和系统服务:

ps-axopid,ppid,user,%cpu,%mem,rss,state,lstart,command\|grep-E'[s]yspolicyd|IntelliJ IDEA|Codex|CC Switch'

确认syspolicyd是否报文件句柄耗尽:

log show--last10m--stylecompact\--predicate'process == "syspolicyd"'\|grep-E'UNIX error exception: 24|Failed to generate SecStaticCode'

检查句柄总数和重复目标:

sudolsof-nP-p"$(pgrep-xsyspolicyd)"|wc-lsudolsof-nP-p"$(pgrep-xsyspolicyd)"\|grep'/Applications/'\|awk'{print $9}'\|sort\|uniq-c\|sort-nr\|head

结束已经确认的应用空壳:

kill<空壳PID>

重启系统策略服务:

sudokillallsyspolicyd

重新启动 IDEA:

open-na"IntelliJ IDEA"

确认 IDEA 完整启动:

ps-axopid,ppid,%cpu,%mem,rss,state,lstart,command\|grep'/Applications/IntelliJ IDEA.app/Contents/MacOS/idea'\|grep-vgreptail-n100"$HOME/Library/Logs/JetBrains/IntelliJIdea2026.1/idea.log"

十四、最终判断

本次问题不是一个单点故障,而是两层问题叠加:

第一层: IDEA 的 Java2D Metal 渲染线程卡死 ↓ 用户强制退出 IDEA 第二层: macOS syspolicyd 已发生文件描述符泄漏/耗尽 ↓ 新 IDEA 在 JVM 和动态库装载阶段卡住 ↓ LaunchServices 认为应用已经启动 ↓ 再次点击图标或 open -a 看起来完全没反应

因此,最终解决方案也分为两部分:

  1. 恢复启动能力:结束应用空壳,并重启syspolicyd
  2. 降低 IDEA 再次卡死概率:加入-Dsun.java2d.metal=false

对于 Codex 和 CC Switch:

  • 它们与 IDEA 不是同一个应用级故障;
  • 但很可能共享同一个 macOS 系统启动层故障;
  • 本次 Codex 明确与syspolicyd的重复文件句柄现象相关;
  • 以前两次由于没有保存现场日志,只能归类为高度相似,不能做百分之百的历史追溯。

如果以后再次发生,优先执行本文的“5 分钟无重启恢复流程”,不需要一开始就重启整台 Mac、重装应用、删除配置或重新签名 App。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询