ARTICLE DETAIL

资讯详情

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

JetBrains IDE插件加载失败排查:从“2 entries did not activate”到根因解决

JetBrains IDE插件加载失败排查:从“2 entries did not activate”到根因解决 我记得很清楚那天下午发生了什么我坐在工位前刚把 IntelliJ IDEA 升级到最新版本重启之后插件市场一片灰控制台里滚过一行报错——failed to load plugins web boot: 2 entries did not activate。当时我以为是某个插件坏了于是逐个禁用、重装、清缓存折腾了整整两个小时最后发现根本不是某个插件的问题而是整个plugins加载链路里一个非常隐蔽的环节出了岔子。这个报错字符串在网上被搜烂了但真正把它讲透的文章少之又少。绝大多数帖子只会告诉你删掉plugins目录再重启可如果你照着做了还是报错接下来就完全没人管你了。这篇文章想做的就是把plugins加载失败这件事从现象到根因完整拆一遍这个报错到底在说什么、日志里的每一条信息该怎么读、有哪些不起眼但破坏力极大的隐藏坑以及当你自己写 plugin 时加载机制又是怎么运作的。不管你是被报错困扰的普通用户还是准备深入插件开发的人这篇文章里应该都有你能直接拿走用的东西。我尽量不用那些绕来绕去的官方话术就按我实际排查的顺序来写包括我踩进去又爬出来的那些坑。1. failed to load plugins web boot: 2 entries did not activate到底在说什么先解决一个基本问题这段报错信息不是中文用户常见的翻译错误也不是什么随机的系统噪音它是 JetBrains 系 IDEIntelliJ IDEA、PyCharm、WebStorm、GoLand 等在插件管理器启动阶段打印的一条日志。它的出现位置通常有两个一个是 IDE 启动时的系统日志另一个是idea.log文件里。很多人第一次看到它是在Help | Show Log in Explorer打开的日志目录里旁边还跟着一堆带有包路径的异常堆栈。要理解这条报错你首先得知道 JetBrains 平台的插件加载机制和普通软件不太一样。IDE 启动时并不会一次性把plugins目录下所有东西全部灌进 JVM而是有一个严格的启动引导阶段。插件被分成两类一类是必须由引导核心加载的底层插件比如附带了自定义类加载器、给 JVM 打桩、或者需要参与 IDE 内核初始化的插件另一类是普通的功能扩展插件在 UI 层注册菜单、在某些动作触发时执行代码。前者的加载发生在 IDE 主窗口出现之前也就是所谓的web boot阶段JetBrains 内部把它称为 Platform Boot。web boot里的web可能会误导你它跟网站、HTTP、网络服务没有任何关系指的是 IDE 最外层壳程序bootstrap拉起内部平台服务的过程。在这个阶段启动器会读取plugins目录下所有.jar文件以及对应的plugin.xml然后做三件事校验插件 ID 和版本兼容性、建立依赖关系图、把声明了until-build和since-build的插件匹配到当前 IDE 版本。任何一环出了问题这个插件就会被标记为did not activate。那2 entries did not activate的2是哪里来的就是这次的启动过程中被判定为无法激活的插件数量。这个数字每次启动都会重新计算不是你上一次错误留下的残留。我排查过的一个案例里日志显示 1 entry did not activate结果是用户同时装了某个插件的 1.0 和 2.0 两个版本两个 jar 包互相冲突最终 IDE 选择让新版激活、旧版沉默。所以当你看到这个数字第一反应不应该是完了我的 IDE 坏了而应该把它当成一条线索——有 N 个插件在身上背着黑锅先把它们找出来。这段日志本身不是致命的。JetBrains 的启动器在遇到插件加载失败时会采取跳过策略而不是中止策略。IDE 还是会正常打开只是某些功能菜单不见了某些快捷键失效了或者你发现某个插件设置页变成灰色。真正致命的是你把这条日志当成小事忽略掉然后继续在残缺状态里工作等用到某个功能时才发现问题已经越滚越大。2. 插件加载失败的常见原因与排查的第一步把日志当成地图要解决plugins加载问题光盯着那一行报错文本是不够的。它只是结果不是原因。正确的起点是找到完整的堆栈信息。在 IntelliJ IDEA 里打开Help - Show Log in Explorer找到idea.log搜索did not activate或者上报错串中提到的插件 ID。大多数情况下日志里会有一行类似于Plugin xxx failed to initialize或Cannot load plugin ...: this plugin is incompatible with the current version的具体描述。2.1 兼容性规则since-build和until-build在背后做裁决JetBrains 的插件兼容性判断并不神秘每个插件发布时会在plugin.xml里声明兼容的 IDE 版本范围。对于直接下载 zip 包手动安装的插件这个范围由两个标签决定标签作用常见值示例idea-version since-build231.0 /当前 IDE 的内部构建号必须大于等于该值231.0 表示只在 2023.1 及以上启用idea-version until-build233.0 /当前 IDE 的内部构建号必须小于等于该值233.0 表示在 2024.1 及以上停用IDE 自身也有一个 internal build number这个数字可以从Help - About里看到。当你的 IDE 版本刚好超出until-build插件就会被启动器判定为 incompatible于是did not activate的条目里就会出现它的名字。这个机制在商业插件的旧版本上尤其常见。某个插件停更一年后你升级了 IDE它立刻被判了死刑。这不一定代表插件代码完全不能运行只是官方不允许它在更高版本上加载。你可以在 IDE 的插件管理页里勾选 Allow installing plugins from custom repositories 之类的高级设置也可以直接把plugin.xml里的until-build改成一个很大的数字强行加载但这属于踩钢丝我后面会专门说这样做会引起的诡异问题。2.2 插件 A 依赖插件 BB 没加载时 A 也会被标记失败还有一类不太容易第一眼识别出来的原因依赖链断裂。JetBrains 插件可以在plugin.xml声明依赖其他插件比如dependscom.intellij.modules.platform/depends depends optionaltrue config-filemybatis-support.xmlcom.xxx.mybatis/depends第一行表示这个插件必须依赖平台模块这个永远不会缺。第二行则表示如果检测到com.xxx.mybatis这个插件存在就额外加载mybatis-support.xml里定义的扩展点如果不存在就跳过。这种 optional 依赖通常不会导致加载失败。真正会失败的是非 optional 依赖缺失A 写死了要 B而 B 因为兼容性原因被禁用那么 A 也会被牵连日志里可能同时出现两个did not activate。这种连带关系解释了一个很反直觉的现象你明明把出问题的插件卸载了剩下的那个还在报错。其实只要把依赖链另一头的插件也处理掉问题才会消失。2.3 系统版本升级后出现的幽灵加载失败还有一种很隐蔽的情况。某些插件在加载时不会立刻抛异常而是在启动阶段的类初始化里触发一个NoClassDefFoundError它的堆栈里往往出现一些第三方库的名字比如kotlin、gson、guava。这通常是因为插件作者没有把依赖完整打包进插件 jar 里而是依赖 IDE 自带的版本。当 IDE 从一个版本升级到另一个版本时内置库的包名、类路径或方法签名发生了变化插件就崩溃了。这种问题你想通过改配置解决是做不到的唯一的选择就是等插件作者发新版或者卸载后寻找替代品。不过你可以通过一个步骤把插件本身坏了和环境变了导致插件坏了区分开用 IDE 自带的Help - Diagnostic Tools - Compose...之类的工具截图没用直接打开日志看堆栈里的第一个Caused by是什么。如果是NoSuchMethodError或NoClassDefFoundError基本可以断定是插件与当前 IDE 版本之间的内部 API 不匹配而不是你的操作失误。3. 从零开始的完整排查链路我处理一个真实案例的每一步光讲原理有点干我给你完整走一遍我最近处理的一个案例。症状是 WebStorm 启动后一个主题插件和一个数据库工具插件都没有生效日志里出现failed to load plugins web boot: 2 entries did not activate。我按下面这个顺序排查每一步都记录在这里。3.1 第一步定位是哪些插件没激活打开日志后先搜did not activate这一次的日志片段长这样2024-XX-XX 10:12:33.123 INFO c.j.p.m.PluginManager - Plugin Material Theme UI (id: com.chrisrm.idea.theme) did not activate except: PluginDescriptor... 2024-XX-XX 10:12:33.126 INFO c.j.p.m.PluginManager - Plugin Database Tools and SQL (id: com.intellij.database) did not activate except: PluginDescriptor...这里com.chrisrm.idea.theme是主题插件com.intellij.database是 WebStorm 内置的数据库插件。数据库插件是 JetBrains 自己随 IDE 分发的它加载失败很反常说明问题不是简单的第三方插件太旧。3.2 第二步查看插件目录的实际文件在Help - Show Log in Explorer打开的目录里往上走一级就是 IDE 的配置目录plugins文件夹就在旁边。我打开后发现有两个MaterialTheme相关的 jar 文件一个位于plugins/MaterialThemeUI/lib/下另一个位于用户级目录config/plugins/里。这两个 jar 的版本号不一样。这就是典型的重复安装问题。如果你曾经从 JetBrains 插件市场安装过一次之后又从官网下载 zip 包手动覆盖安装用户级目录和 IDE 安装目录里可能各有一份。启动器扫描到同一插件 ID 的两个实例时会选择一个加载另一个标记为 failed。日志里第二个条目的did not activate就是被判定为重复的旧版本。处理办法很直接保留其中一个删掉另一个。保留原则是选版本新的装在你希望长期使用的层级里。我的习惯是把第三方插件统一放到用户级config/plugins目录IDE 安装目录只留内置插件这样升级 IDE 时不容易搞混。3.3 第三步数据库插件为何也不激活数据库插件是 JetBrains 内置的它失败通常是另一个原因。我翻它对应的详细日志发现了一段关键堆栈Caused by: java.lang.IllegalStateException: duplicate key com.intellij.database:...duplicate key这个错误说明了什么说明这个插件的扩展点被重复注册了。为什么会被重复注册因为前一次异常退出时IDE 在config/plugins下生成了这个插件的索引或者备份文件和安装目录里的版本形成了双份。我在config/plugins下找到一个残留的database文件夹删除后重启问题消失。这个步骤很多人容易漏掉。遇到内置插件加载失败时先不要往软件坏了的方向想先看是不是自己在某个时间点误操作过它的配置文件或目录导致重复注册。3.4 第四步处理完重复项后还需要清一次索引缓存删除目录后直接重启我的第一反应是总算好了结果插件列表里仍然显示两个插件未能加载。原因是 IDE 的插件索引缓存没有刷新启动器在前 3 秒还会读到旧的元数据。清理方式是彻底退出 IDE删除config/plugins目录下的.idea索引相关文件不同版本位置不太一样保险起见看idea.log里报的缓存路径再删除system/plugins下的临时文件最后重启。注意system目录位于配置目录下不是安装目录别删错了。如果你不想手动找用 IDEA 自带的File - Invalidate Caches and Restart也行但这个方法对重复插件导致激活失败的清理不够彻底因为它主要重建的是项目索引不一定会删除插件扫描缓存。所以我更推荐手动删除system目录下的 plugin 临时文件夹代价是重启后 IDE 需要两三分钟重建缓存但换来的是干净状态。3.5 第五步验证加载是否恢复正常重启后打开Help - About页面下方的插件列表确认两个插件都处于 enabled 状态。再打开日志搜索did not activate如果没有新条目出现说明排查结束。如果还有重复第一步到第四步的流程但要注意看新日志里的插件 ID 是否换了如果换了说明你已经解决了旧问题但还有新问题跟之前是一回事还是两回事要分清楚。4. 排除加载阶段的雷区目录结构、Zip 包和自定义文件第一批从日志定位成功的案例还算顺利。但插件加载失败的高发地带其实不在加载本身而在于你安装插件的方式出了问题。JetBrains 插件不是随便把一个 zip 包丢进目录就能用的它对目录结构和文件格式有很多约定。这里我挑几个最常踩的雷区说。4.1 千万别把解压后的文件夹直接命名为插件的英文名很多插件在官网提供的下载文件是一个 zip 包zip 内部的结构五花八门。有的包解压后直接就是一个 jar 和一堆 lib 文件夹有的包解压后是一个外层文件夹文件夹里才是真正的插件内容。如果你把外层文件夹整个丢进plugins目录启动器会在该文件夹第一层找plugin.xml找不到就不加载。更麻烦的是有些 zip 包解压后最外层还有一个__MACOSX目录里面是 MacOS 的资源分支文件这些文件会干扰 IDE 的文件扫描。正确做法是解压后先看是不是有lib目录和META-INF/plugin.xml。如果你看到的第一层是一个同名文件夹那么应该进入这个文件夹把里面的lib目录和plugin.xml所在的整个层级放到plugins目录下而不是把外层壳也放进去。4.2 版本号里的内部构建号和You dont see a version的坑有一种非常经典的情况你下载了一个插件打开它的plugin.xml发现里面是这样写的idea-version since-build203.5984 until-build213.*/而你用的 IDE 是 2022.1内部构建号 221.5787.32。按照字面意思这个插件只支持到 213也就是 2021.3你的 IDE 应该是太新了。有些人会用文本编辑器强行把until-build改成222.*然后重启。这样做有时候能加载但如果你足够倒霉会遇到一堆奇怪的 UI 错乱比如菜单项出现在不该出现的地方或者打开设置页直接崩溃。这是为什么因为until-build不只是一个静态标记它决定了 IDE 是否允许插件代码访问那些在新版本里被删除或移位的内部 API。JetBrains 每次大版本更新都会重构相当一批类插件如果没经过新版本的适配测试就强行加载运行时必然出问题。强行改until-build属于知道风险但还是要试一试的玩法我的建议是改可以但一定要先备份原 jar并且只在不重要的环境里验证。4.3 Plugin is incompatible提示出现但你确信版本没问题这种提示还有一种来源IDE 的plugins目录里存在空文件夹。空文件夹不会被扫描出什么问题但如果你之前卸载插件时只删了 jar 却留下了包含旧plugin.xml的残留目录扫描器就会认为这是一个已经退役的插件版本。日志里会显示为Plugin is incompatible但它并不是真的因为版本不匹配而是元数据读取不完整导致无法创建插件描述符。遇到这种问题最省事的办法是完全退出 IDE打开plugins目录手动查看有没有只包含几个零散文件且结构不完整的目录有就整个删掉。你不需要担心误删正常插件的目录因为正常插件目录里一定至少有lib文件夹和META-INF/plugin.xml两个标志物。4.4 自定义插件仓库的信任问题有些插件不在官方市场里而是作者放在个人服务器上提供了自定义仓库地址。你在Settings - Plugins - Gear icon - Add Plugin from URL...里填地址安装。这类插件加载失败时日志往往显示Plugin cannot be loaded: ... signature verification failed或者certificate expired。JetBrains 对插件签名是有一个信任链的官方市场里下载的插件都带签名。从任意 URL 安装的插件如果没带签名或者签名过期现代版本的 IDE 会拒绝加载。遇到这个情况你不能绕过去唯一可行的是联系作者要一份新签名的版本或者用idea.ignore.disabled.pluginstrue配合带内部配置启动这个开关只适合调试千万不要在日常使用里开着。5. 日志之外的环境因素代理、缓存目录和宿主机的非技术坑插件加载失败你查来查去发现代码和目录都没问题这时大概率是环境层面出了幺蛾子。这类问题容易让人崩溃因为它隐藏得很深而且不同的人环境差异很大网上很难搜到一模一样的帖子。5.1 代理导致插件市场能打开但插件无法激活有一次我帮同事排查他的 IDEA 一直提示某些插件加载失败但是插件市场页面能正常打开插件列表也能看到唯独加载报错。我一度怀疑是他的插件文件下载不完整。后来在idea.log里看到一行超时异常指向一个国外地址。检查发现他在 IDE 设置里配了代理代理对某些资源过滤或超时导致 IDE 启动时尝试从远端校验插件信息失败于是启动器把未能完成校验的插件标记为不激活。这个问题的特征是报错在日志里出现的时间点非常晚不是启动开头而是启动进行到一半。解决办法是在Settings - Appearance Behavior - System Settings - HTTP Proxy里选择 Auto-detect proxy settings 或 No proxy然后重启。如果你的使用场景确实必须挂代理那你需要在代理配置里允许 IDE 访问plugins.jetbrains.com并确保没有对.jar后缀做缓存拦截。5.2 磁盘空间不足导致插件被截断这个坑我在别人机器上见过不止一次。IDE 启动时会解压部分插件内容到system目录如果磁盘空间只剩几百 MB解压到一半就会失败失败的结果同样是did not activate。但日志里的堆栈会比较特殊你会看到java.io.IOException: No space left on device或者ZipException。解法没什么技术含量就是清理磁盘空间。但为什么特别值得写出来因为你如果盯着plugins目录看永远不可能发现问题因为它只是被解压方不是解压的落点。需要同时检查的是system分区尤其是你把 IDE 配置目录放到自定义路径后这个分区很可能和安装分区不在同一个盘上。5.3 权限问题IDE 以管理员权限安装却以普通权限运行Windows 上比较常见。安装 IDE 时如果使用了管理员账户安装目录的写入权限可能对普通用户不开放。之后如果你换了普通账户登录IDE 在启动时发现自己的安装目录不可写无法更新插件也无法写入临时文件加载就会失败。日志里会出现AccessDeniedException但位置比较隐蔽。这个问题的解决方案有两个层面要么把 IDE 安装目录的写权限授予当前用户要么干脆把 IDE 安装到用户目录下。JetBrains 系的产品其实很建议装在用户目录这样可以省掉一堆权限相关的毛病。如果你已经装在C:\Program Files下至少要把plugins目录的修改权限给全。5.4 杀毒软件或公司安全策略拦截了 jar 加载给企业内部环境用的机器有时候会出现一种很诡异的情况日志没有异常插件也显示正常启用但运行时对应的功能就是不出来点菜单也没反应。这种时候我会手动确认一下插件 jar 的真实大小和压缩包里的文件数量。有两次我发现杀毒软件把插件里某个 class 文件当作风险文件直接删除了导致 jar 包在解压时遇到缺失文件IDE 选择默默降级处理。如果你在受管控的电脑上工作并且plugins加载问题反复出现可以尝试在杀毒软件里将被删除的文件恢复并且把 IDE 的安装目录和配置目录加入白名单。这个操作比任何 IDE 内部的设置都有效。6. 当它是你亲手写的插件时从零理解激活流程被一个现成插件折腾完一轮后我自己也动了手写插件的念头。如果你准备开发自己的 IDEA 插件那么failed to load plugins web boot这条报错对你来说就更有意义了因为你会在开发和调试阶段反复看到它。这一节讲的是从插件作者视角看激活流程到底经历了哪些步骤。6.1 插件的骨架plugin.xml 里必备的几个字段一个能被正常激活的插件它的META-INF/plugin.xml至少要包含这些信息idea-plugin idcom.example.myplugin/id nameMy Plugin/name vendorexample.com/vendor descriptionDemo plugin for blog post/description version1.0.0/version idea-version since-build231.0/ dependscom.intellij.modules.platform/depends extensions defaultExtensionNscom.intellij !-- 在这里声明你的扩展点 -- /extensions /idea-pluginID 是全局唯一的标识符。如果你想发布到 JetBrains 官方市场这个 ID 不能和已有插件重复。如果重复IDE 在本地加载时会用后写的那个覆盖先写的如果你同时在开发两个 ID 一样的插件它们当中必然会有一个did not activate。depends的作用不只是声明依赖它还决定了插件的启动时机和可用的 API 范围。com.intellij.modules.platform是最基础的依赖几乎每个插件都要声明。如果你想用到 Java 相关的模块还需要额外声明com.intellij.modules.java。漏掉这个依赖不会导致编译失败但运行时你调用的PsiJavaFile等类会因找不到模块而抛错。6.2 为什么我的插件在本地跑得好好的打包后装上去就不激活这是新手开发者的经典问题。你在 IDE 里用 Gradle 的runIde任务调试时一切正常但把build/libs下的 zip 包安装到另一个 IDE 里它却显示无法激活。最常见的原因有两个。第一你打包用的是jar任务而不是buildPlugin任务。后者会生成一个包含所有依赖的完整 zip 包前者只把你自己写的 class 打进去缺少第三方依赖库。IDE 启动时找不到依赖库直接标记为加载失败。第二plugin.xml里声明的since-build比目标 IDE 的版本高。用runIde调试时Gradle 会自动帮你启动一个匹配版本的 IDE所以感知不到版本不匹配。一旦你手动装到旧版本 IDE 上就会被拒之门外。我建议每次打包前都看一眼构建配置里的intellij.version确认和你准备安装的目标 IDE 大版本一致。6.3 检测插件加载结果的一个通用小技巧不管你是插件用户还是作者想要确认插件是否成功激活有一个比看日志更直观的方法在 IDE 里打开Help - Find Action输入你插件中注册的 Action ID 或菜单名称。如果能在搜索结果里看到说明插件至少已经注册成功如果搜不到说明它在扩展点注册阶段就被跳过了。这个方法对很多 UI 层面的插件加载问题非常有效比翻日志快得多。6.4 自定义扩展点的激活顺序与依赖JetBrains 插件平台允许插件 A 声明自己在插件 B 加载后再执行某些逻辑这是通过depends的可选属性实现的。你现在看可能觉得没什么但真到开发复杂的跨插件功能时你一定会踩到我的插件在别人插件之前加载导致找不到对方提供的服务这个坑。单独的解决办法是在代码里用ServiceManager.getService()时做空值判断不要假设依赖一定存在。真正的插件社区里这种假设是导致插上了但功能不工作的头号原因。7. 我留下的最小可用检查清单再遇到加载失败可以这样收尾排查到这里你手里应该已经有了一套自己的方法。为了让你下次不用再来翻这篇文章我把整个过程中的思考沉淀成一份最小可用的检查清单。它不是官方文档是我在不同电脑上反复验证后整理出来的你照做基本不会错。第一步打开idea.log搜索did not activate记录所有失败插件的 ID。第二步逐个检查是否出现重复安装、残留目录、空目录、文件损坏。第三步检查插件plugin.xml中的since-build和until-build是否覆盖你的 IDE 版本。第四步确认plugins目录结构和官方文档一致不要有多余的壳目录。第五步检查系统目录system所在分区剩余空间是否充足权限是否可写。第六步确认代理设置不会拦截对 JetBrains 插件源的访问。第七步如果以上全部没问题清理系统索引缓存完全重启 IDE。第八步还不行就考虑是不是杀毒软件动了 jar 内部文件。这套清单对 JetBrains 全系 IDE 都有效。IntelliJ、PyCharm、WebStorm、GoLand、DataGrip 共用同一个插件平台机制报错日志的格式、目录结构、排查思路几乎一致。换句话说你今天在这篇文章里学到的换一个 IDE 依然能复现整个过程。我个人实际操作的体会是plugins加载失败的问题百分之七十出在重复安装和目录残骸上百分之二十出在版本兼容和依赖缺失上只有百分之十是真正让人绝望的环境问题。如果你按清单走一遍还没解决建议别在单个插件上无限深挖而是把 IDE 重置到干净状态然后分批装回插件。每装一批就重启一次加载失败的这个插件自然就会被精确锁定出来。最后再分享一个我自己的习惯下载插件的 zip 包后我会先把它解压到一个临时目录用tree命令看一眼结构确认里面有lib目录和META-INF/plugin.xml再复制到plugins目录下。这样处理过的插件我几乎没见过加载失败的。这个习惯只需要多花十秒钟但省掉的时间远远超过十秒。
返回列表