ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

IntelliJ IDEA启动崩溃排查:Internal error与java.util.concurrent异常全解析

IntelliJ IDEA启动崩溃排查:Internal error与java.util.concurrent异常全解析 使用 IntelliJ IDEA 的人十个里至少有九个见过那个写着 “Internal error. Please refer to https://jb.gg/ide/critical-startup-errors” 的启动失败窗口。我处理过不少次这类问题每次同事发来的截图异常信息都断在 java.util.concurr 这个位置后面就没了下文。这个截断不是乱码而是 IDEA 启动早期的弹窗在堆栈还没完全展开时就被打断了真正的原因根本不在弹窗里。这篇文章把我处理这类 java.util.concurrent 启动崩溃的完整路径写出来从看日志、定位插件、清缓存到调 JVM 参数最后给一套能直接复用的排查清单。适合被这个报错卡住的人也适合负责团队开发环境的人照着去排障。1. 启动窗口只截断了半句异常完整信息一直在日志里等你首先要明确Internal error 不是一个具体的故障而是 IDEA 给所有“启动早期严重异常”套的统一外壳。官方给你的那个 jb.gg 链接是让你提交诊断信息或获取反馈入口的并不是“打开这个网址就能自动修复”。真正有价值的信息在弹窗被截断的部分以及 IDEA 自己记录的完整启动日志里。1.1 弹窗只显示半句是因为启动线程已经处于半崩溃状态IDEA 启动时会同时做很多事加载 JVM、读取配置、初始化插件容器、恢复上次会话、建立本地文件监视器、准备索引框架。这些任务分布在不同线程里主线程一旦发现某个关键任务没有按时完成或者子线程抛出了未捕获异常就会弹 Internal error 窗口。弹窗里的异常文本通常来自最外层的包装异常比如 java.util.concurrent.ExecutionException而真正的 Caused by 还没拼接完于是你看到的就只有一个类名前缀 java.util.concurr。这不算 IDEA 故意偷懒。对普通用户来说这个窗口的首要任务是“告诉你出事了”而不是把完整堆栈全铺出来——大多数用户看到完整堆栈反而更慌。但对排障的人来说必须知道完整堆栈在日志里。1.2 拿到完整日志的三种方式如果 IDE 还能偶尔启动到欢迎页首选方式是直接用菜单 Help - Show Log in ExplorerWindows 下是资源管理器macOS 下是 Finder它会自动打开存放 idea.log 的目录。如果 IDE 完全起不来就按系统去找日志目录系统日志文件常见位置Windows%APPDATA%\JetBrains\IntelliJIdea版本\log\idea.logmacOS~/Library/Logs/JetBrains/IntelliJIdea版本/idea.logLinux~/.cache/JetBrains/IntelliJIdea版本/log/idea.log注意版本目录名不同比如 2024.1、2024.2取最新的那个。还有一种更接近底层的办法在安装目录的 bin 下找到 idea.batWindows或 idea.shLinux/macOS用命令行手动启动把控制台输出重定向到文件里。这样连系统标准输出里被吞掉的细节都能看见。1.3 从日志中锁定第一条 ERROR 和 Caused by打开 idea.log 后不要从末尾开始读也不要从头傻傻地啃。先搜索关键词 ERROR找到文件中第一条 ERROR 的位置从这里往下读两三百行。大多数启动崩溃的根因就在第一条 ERROR 附近。接下来再搜 Caused by这个词后面才是异常链的真正源头。一段典型的日志可能长这样java.util.concurrent.ExecutionException: com.intellij.diagnostic.PluginException: Cannot create class com.example.someplugin.MainPanel [Plugin: com.example.someplugin] at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:205) Caused by: com.intellij.diagnostic.PluginException: Cannot create class com.example.someplugin.MainPanel [Plugin: com.example.someplugin] at com.example.someplugin.MainPanel.init(MainPanel.java:81) at com.example.someplugin.loader.PanelLoader.load(PanelLoader.java:34) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)看到 Caused by 后面出现第三方插件类名以及[Plugin: ...]标签基本就能锁定问题出在哪个插件上。这一步是整个排查里最关键的定位动作。2. java.util.concurrent 在启动阶段冒出来到底是谁在并发很多人一看到 java.util.concurrent 就以为 IDEA 内部的并发框架坏了实际不一定。这个包名最多说明“有一个后台任务执行失败了”真正的失败原因还得往 Caused by 里继续挖。2.1 IDEA 启动时为什么会跑一堆并发任务IDEA 不是单线程把启动流程走完的。它内部维护了一组线程池用来执行插件加载、项目模型解析、代码索引启动、外部进程探测这些不能阻塞 UI 的任务。你可以把启动过程想象成餐厅备菜有人洗菜、有人切菜、有人烧水、有人搬桌椅各干各的主线程在门口等所有人就绪。任何一个人中途翻车负责收尾的领班就会收到一份包装好的“事故报告”在 Java 里这个包装通常就是 ExecutionException 或 CompletionException。所以 java.util.concurrent 出现在报错里只能说明“某个后台任务执行失败了”不代表并发框架本身有问题。这一点想明白后面排查就不会跑偏。2.2 几种常见 concurrent 包装异常的含义我把启动阶段常见的 concurrent 异常整理成一张表方便对号入座异常类大概含义启动场景中最常见的诱因java.util.concurrent.ExecutionException任务在运行阶段抛出了异常被 Future 包装插件初始化方法抛错java.util.concurrent.CompletionException同 ExecutionException出现在 CompletableFuture 链中异步索引或插件加载任务异常java.util.concurrent.TimeoutException任务超过等待时间未完成插件同步等待外部服务或文件锁死java.util.concurrent.CancellationException任务在完成前被取消多个插件竞争资源导致任务被上层取消java.util.concurrent.RejectedExecutionException线程池拒绝接受新任务线程池已关闭但插件还在提交任务启动时遇到最多的是前两种。后三种偶尔出现。比如我曾经遇到一个代码统计插件在启动时联网请求许可证网络超时后加载任务一直挂起最终弹出 TimeoutException。问题不在 IDEA而是那个插件自身行为不稳。2.3 一个典型的 ExecutionException 日志长什么样再把前面那段日志切片讲细一点。第一行的 ExecutionException 是“外层包装”看到它不用慌。真正要看的是往下走的 Caused by那里会告诉我们失败原因是什么。比如日志中出现PluginException: Cannot create class后面跟着插件类名说明这个插件在加载组件时直接抛了异常。继续往栈帧下方看凡是com.example、org.someplugin这类第三方包名出现的行基本就是罪魁祸首所在。还有一种情况整个 Caused by 链里都是 com.intellij 内部类的栈帧没有一个第三方包名。这时候问题往往不是某个插件而是项目配置或缓存损坏。两者的排查方向完全不同所以读日志时一定要耐心看到最底层。3. 排查启动崩溃的顺序别急着卸载重装很多人遇到这类报错第一反应是卸载重装或者到处找“新版激活”之类的捷径结果重装完问题原样出现。我建议先按顺序排查百分之八九十的 Internal error 不用走到重装那一步。3.1 先回答三个问题开始动工具之前先问自己三个问题这次报错能稳定复现吗如果只是偶尔一次重启往往就好。最近一次正常启动之前我做过什么改变是升级了 IDEA、装了新插件、改过 vmoptions还是切换了 JDK崩溃是打开特定项目才出现还是连欢迎页都进不去这三个问题的答案基本能决定排查方向。比如“升级后连欢迎页都进不去”优先怀疑配置迁移不兼容“只有打开老项目时才崩”优先怀疑项目缓存或 .idea 目录损坏“最近刚装了一个插件之后开始崩”优先禁插件。3.2 用二分法找到引发异常的插件如果日志里明确指向某个插件直接禁用或移走。如果日志里只泛泛写着 ExecutionException没有插件名就得做插件隔离测试。IDEA 能正常进欢迎页时可以通过设置里的 Plugins 页面逐个禁用然后重启观察。更快的方式是直接把整个用户级插件目录改名让 IDEA 在“没有第三方插件”的状态下启动。用户级插件目录的位置通常是系统插件目录常见位置Windows%APPDATA%\JetBrains\IntelliJIdea版本\pluginsmacOS~/Library/Application Support/JetBrains/IntelliJIdea版本/pluginsLinux~/.local/share/JetBrains/IntelliJIdea版本/plugins把整个 plugins 文件夹重命名成 plugins_bak再启动。如果“裸插件”状态下能正常打开说明问题确实出在插件上。接下来启用一半插件再测试再把可能出问题的一半分成两半继续试。这个二分法看起来笨但比一个个试要快得多。我处理过的一个案例一个主题插件和一个代码统计插件在更新后同时初始化互相踩了对方的资源单禁其中一个都不会恢复只有同时禁掉才正常。这种组合冲突不二分你很难快速找到。3.3 代码层面异常与配置层面异常的区分同样的外包装异常根因可能是代码层也可能是配置层。代码层问题多见于插件加载失败、初始化方法空指针日志里会给出明确的栈帧和行号。配置层问题则可能是 vmoptions 里有不合理参数导致线程创建失败。区分方法是看 Caused by 链的底层如果是 OutOfMemoryError先调内存如果是 ClassNotFoundException、PluginException先处理插件。不要只看外层异常就下结论。4. 缓存和索引损坏比你想的更常制造 Internal error有一类 Internal error 和插件无关而是项目缓存或系统索引目录损坏。这类问题有一个明显特征往往只出现在打开某个特定项目时或者每次启动到“正在索引”阶段就卡死然后弹 Internal error。4.1 哪些缓存文件最容易坏IDEA 的每个项目会在 .idea 目录下保存一堆 xml 文件比如 modules.xml、workspace.xml、misc.xml。其中 workspace.xml 因为频繁写入在断电、死机、强制杀进程之后特别容易损坏。另一个重灾区是 IDEA 系统目录里的索引库默认在 Windows 的C:\Users\用户名\AppData\Local\JetBrains\IntelliJIdea版本\system或对应平台的~/.cache/JetBrains/...目录。索引是一堆二进制文件进程被杀、磁盘空间不足、文件权限变化都可能让索引不完整。索引损坏后启动时会反复读取这些文件并发的索引线程就会抛异常。4.2 进不了 IDE 时怎么清缓存能正常进欢迎页时直接 File - Invalidate Caches / Restart勾选 Clear file system cache and Local History让 IDEA 清理缓存后自动重启。但如果连欢迎页都进不去只能手动来。手动删除的原则是只删 system 目录下的缓存子目录不要动 config 目录。找到 system 目录后先整个备份一遍再把 index、caches、compiler 这类子目录分别改名或移走再启动。这里关键的一点是千万不要删 config 目录否则你的键位设置、主题、插件配置全部会被重置。如果问题只在某个特定项目出现可以尝试只删除项目下的.idea/workspace.xml让 IDEA 重建项目视图。很多“打开项目就崩”的问题靠这一招就能解决。4.3 清缓存之后为什么有时会复发清完缓存还是不行的情况也不少。如果索引刚重建完又崩溃通常不是缓存本身的问题而是底层条件不允许缓存正常写入。常见诱因包括磁盘剩余空间不足、JetBrains 目录被设置成只读、杀毒软件锁定了索引文件、代码仓库里存在异常的长路径或大量符号链接。检查顺序建议是先看磁盘空间至少留出 10GB再把 JetBrains 相关目录加入杀毒软件白名单最后检查项目内有没有超长路径。Windows 下可以用资源监视器查看哪个进程锁定了文件macOS/Linux 下可以用 lsof 命令查句柄。解决这些底层问题之后再清一次缓存基本就能稳定。5. JVM 参数和内存设置concurrent 异常的另一个幕后推手还有一种情况会让你误以为问题在插件或缓存IDEA 的 JVM 参数被调得过于激进启动并发任务直接撞上内存天花板。5.1 并发线程创建失败与内存限制的关系IDEA 启动时并发任务多线程数自然也多。JVM 每创建一个线程除了 Java 堆内存之外还要分配线程栈内存。如果系统可用内存不足或者-Xss设置过大线程创建就会失败抛出java.lang.OutOfMemoryError: unable to create new native thread。这个错误一旦发生通常会被线程池包装成 ExecutionException 或 RejectedExecutionException最终在弹窗里表现为 Internal error。所以不要一看 java.util.concurrent 就去调-Xmx。如果错误底层是线程创建失败盲目调大堆内存反而会抢占操作系统内存让线程创建失败更严重。5.2 在不同物理内存下设置 vmoptions 的参考基线我平时用的一套比较保守的 vmoptions 参数如下可以在此基础上根据项目大小微调物理内存建议 -Xms建议 -Xmx备注8GB512m2g不要同时开太多大项目16GB1g4g大多数中大型项目够用32GB2g8g本地跑微服务集群再考虑更大修改方式是 Help - Edit Custom VM Options然后编辑 idea.vmoptions。两个要点-Xmx不要超过物理内存一半-Xss不要超过 2m。我见过有人为了防栈溢出把-Xss调到 16m结果每次启动都卡在创建线程池阶段最后弹 Internal error。5.3 改 vmoptions 之后还报错怎么办如果你调整参数后依旧报 java.util.concurrent 相关异常先确认你改的是不是正确的 vmoptions 文件。IDEA 存在两套配置一套是安装目录下的 bin/idea64.exe.vmoptions另一套是用户目录下的自定义 vmoptions。Help - Edit Custom VM Options 打开的是用户级文件有更高优先级。但如果你之前手动改过安装目录下的文件可能会被版本升级覆盖掉。排查时可以打开 Help - Edit Custom VM Options把所有内容清空重新填一套干净参数确保没有拼写错误或残留的无效 JVM 标志。然后再看启动日志如果底层异常依旧和内存无关再把关注点放回插件和缓存上。6. 一套能直接抄的启动崩溃排查清单把前面几节的思路串起来就是一套比较完整的启动崩溃排查流程。我按这个流程走大多数时候能在五分钟内定位到根因。6.1 排查动作与优先级速查表动作解决的问题什么时候做查看 idea.log 的第一条 ERROR 和 Caused by所有问题第一步必须先做重启 IDEA 再试一次偶发并发竞争日志里没有明确错误时重命名用户级 plugins 目录插件加载问题日志提示 PluginException 或最近装过插件删除 system 目录下的 caches/index缓存索引损坏打开特定项目才崩检查并重置 vmoptions线程创建失败、内存不足日志出现 OutOfMemoryError用官方 Toolbox 重装或回退版本版本迁移不兼容以上都无效且发生在升级之后顺序不要颠倒。一上来就重装会把日志和配置都清掉反而让后续排查更难。重装前至少先备份 config 目录。6.2 日常防止启动崩溃的三个习惯第一个是控制插件数量。插件越多启动时注入的后台任务就越多并发冲突概率也会被放大。第二个是定期清理本地历史。IDEA 默认会保存每天的文件快照和本地历史时间长了 system 目录会变得很大索引文件更容易因为写入失败而损坏。第三个是跨大版本升级前先确认常用插件是否兼容新版本。老插件在升级后触发启动期 concurrent 异常是我见过最常见的大版本升级翻车场景。6.3 我自己的处理心得最后说点个人体会。Internal error 这种报错弹窗越吓人根因往往越简单。我经手过的案例里插件问题占了一半缓存损坏占了三成JVM 参数和配置问题占了一成半真正需要重装 IDEA 的情况少之又少。所以下次再看到 java.util.concurr 这种截断别慌先打开日志数数 Caused by再决定下一步动哪里。排查一次之后你会觉得它比想象中好对付得多。
返回列表