IJPL-171566 Invalidate allParents on plugin unload as much late as possible to avoid leaked unloaded class loaders via allParents property

GitOrigin-RevId: 11dda096063fbcad479ada2517a8b84f1fa9134c
This commit is contained in:
Artem.Bukhonov
2024-11-14 21:14:13 +01:00
committed by intellij-monorepo-bot
parent 5af6a06068
commit 42b5833960

View File

@@ -542,8 +542,6 @@ object DynamicPlugins {
unloadDependencyDescriptors(pluginDescriptor, pluginSet, classLoaders)
unloadModuleDescriptorNotRecursively(pluginDescriptor)
clearPluginClassLoaderParentListCache(pluginSet)
app.extensionArea.clearUserCache()
for (project in ProjectUtil.getOpenProjects()) {
(project.extensionArea as ExtensionsAreaImpl).clearUserCache()
@@ -576,12 +574,17 @@ object DynamicPlugins {
@Suppress("TestOnlyProblems")
(ProjectManager.getInstanceIfCreated() as? ProjectManagerImpl)?.disposeDefaultProjectAndCleanupComponentsForDynamicPluginTests()
// clear parents as much late as possible because allParents are a lazy list and calculated on demand
// it may happen that too early invalidation may lead to unloaded loaders appear in allParents again (IJPL-171566)
clearPluginClassLoaderParentListCache(pluginSet)
val newPluginSet = pluginSet.withoutModule(
module = pluginDescriptor,
disable = options.disable,
).createPluginSetWithEnabledModulesMap()
PluginManagerCore.setPluginSet(newPluginSet)
// clear parents cache for newPluginSet just for a case
clearPluginClassLoaderParentListCache(newPluginSet)
}
finally {
try {
@@ -1411,8 +1414,9 @@ private fun setClassLoaderState(pluginDescriptor: IdeaPluginDescriptorImpl, stat
}
private fun clearPluginClassLoaderParentListCache(pluginSet: PluginSet) {
// yes, clear not only enabled plugins, but all, just to be sure; it's a cheap operation
for (descriptor in pluginSet.allPlugins) {
// yes, clear not only enabled plugins, but (all + enabledModules) because enabledModules is a superset of enabledPlugins
// it's a cheap operation and even if some modules may repeat due to concatenation, it should be not a problem (making a set is probably even slower)
for (descriptor in pluginSet.allPlugins + pluginSet.getEnabledModules()) {
(descriptor.pluginClassLoader as? PluginClassLoader)?.clearParentListCache()
}
}