动态插件

走着路睡觉大约 3 分钟

动态插件

从 2020.1版本开始,安装,更新,卸载插件都不需要再重启idea了

开发插件的时候,Auto-Reload 功能支持动态更新项目,

如果插件安装以后需要用户必须重启项目,需要在plugin.xml里配置 require-restart=true:

<idea-plugin require-restart="true">
</idea-plugin>

限制条件

支持 Auto-Reload功能的插件需要满足下面的条件:

不使用Components

如果使用了Components,可以参考 组件 更换为 使用services, extensions, or listeners 来实现相同功能

只能使用动态扩展点

直接使用的和间接使用的(依赖插件所使用的) 扩展点和监听器(Extension Point and Listener List ) 必须都是动态的

自己定义的扩展点也必须是动态的

如果自己定义了扩展点,扩展点也必须设置 dynamic="true",

<extensionPoints>
  <extensionPoint
      name="myDynamicExtensionPoint"
      beanClass="com.example.MyBeanClass"
      dynamic="true"/>
</extensionPoints>

依赖的扩展点的配置

依赖其它扩展点的类,必须实现Configurable.WithEpDependencies 接口

服务不能支持重写

使用的服务 不能设置 overrides="true"

提示

如果需要本地验证插件是否满足以上条件,可以使用 intellij-plugin-verifieropen in new window 进行验证

代码

缓存

在加载和卸载插件的时候使用 CachedValuesManager清空所有缓存

不能保存 PSI(Program Structure Interface)

加载和卸载插件的时候,不能保存PSI element, 建议使用 SmartPsiElementPointer

不要使用 FileType/Language

使用string 替换 Language.getID()/FileType.getName()

加载/卸载事件

注册 应用监听器 DynamicPluginListeneropen in new window 来监听插件的加载/卸载事件

这也可以被用于,例如取消长时间运行的活动,或由于某个进程正在进行而禁止卸载。

故障排除

卸载或更新插件时,IDE 会同步等待插件卸载完成,如果卸载失败,则请求重新启动IDE,

使用最新版本的IDE排查故障,可以在 issuesopen in new window 查找相关问题

日志

事件类的相关日志都用 com.intellij.ide.plugins.DynamicPlugins 记录

内存泄漏

通过以下几步排查:

  1. 验证是否在build(build.gradle.kts或 build.gradle)文件中设置了 -XX:+UnlockDiagnosticVMOptions
  1. 设置 Registry key ide.plugins.snapshot.on.unload.fail = true

  1. 重新加载插件

  2. 打开 .hprof 内存快照文件 (idea可以直接打开)

  3. 查找带插件id的 PluginClassLoader

  4. 查看对 PluginClassLoader 实例的引用

日志参考如下

2020-12-26 14:43:24,563 [ 251086]   INFO - lij.ide.plugins.DynamicPlugins - Snapshot analysis result: Root 1:
  ROOT: Global JNI
  sun.awt.X11.XInputMethod.clientComponentWindow
  com.intellij.openapi.wm.impl.IdeFrameImpl.rootPane
  com.intellij.openapi.wm.impl.IdeRootPane.myToolbar
  com.intellij.openapi.actionSystem.impl.ActionToolbarImpl.myVisibleActions
  java.util.ArrayList.elementData
  java.lang.Object[]
  com.example.ActionExample.<class>
  com.example.ActionExample.<loader>
* com.intellij.ide.plugins.cl.PluginClassLoader

其它问题

可以清空下sandbox试试

上次编辑于:
贡献者: zhaojingbo
Loading...