diff --git a/platform/core-impl/src/com/intellij/ide/plugins/cl/PluginClassLoader.java b/platform/core-impl/src/com/intellij/ide/plugins/cl/PluginClassLoader.java index f60fb9c20978..0e660f2870e3 100644 --- a/platform/core-impl/src/com/intellij/ide/plugins/cl/PluginClassLoader.java +++ b/platform/core-impl/src/com/intellij/ide/plugins/cl/PluginClassLoader.java @@ -52,6 +52,8 @@ public final class PluginClassLoader extends UrlClassLoader implements PluginAwa private final int instanceId; + private volatile int state = ACTIVE; + public PluginClassLoader(@NotNull List urls, @NotNull ClassLoader @NotNull [] parents, @NotNull PluginDescriptor pluginDescriptor, @@ -90,6 +92,16 @@ public final class PluginClassLoader extends UrlClassLoader implements PluginAwa } } + @ApiStatus.Internal + public int getState() { + return state; + } + + @ApiStatus.Internal + public void setState(int state) { + this.state = state; + } + @Override public int getInstanceId() { return instanceId; diff --git a/platform/core-impl/src/com/intellij/ide/plugins/cl/PluginAwareClassLoader.java b/platform/extensions/src/com/intellij/ide/plugins/cl/PluginAwareClassLoader.java similarity index 78% rename from platform/core-impl/src/com/intellij/ide/plugins/cl/PluginAwareClassLoader.java rename to platform/extensions/src/com/intellij/ide/plugins/cl/PluginAwareClassLoader.java index 93521a3ffe96..9eed9d86ed05 100644 --- a/platform/core-impl/src/com/intellij/ide/plugins/cl/PluginAwareClassLoader.java +++ b/platform/extensions/src/com/intellij/ide/plugins/cl/PluginAwareClassLoader.java @@ -3,12 +3,16 @@ package com.intellij.ide.plugins.cl; import com.intellij.openapi.extensions.PluginDescriptor; import com.intellij.openapi.extensions.PluginId; +import org.intellij.lang.annotations.MagicConstant; import org.jetbrains.annotations.NotNull; import java.net.URL; import java.util.Collection; public interface PluginAwareClassLoader { + int ACTIVE = 1; + int UNLOAD_IN_PROGRESS = 2; + @NotNull PluginDescriptor getPluginDescriptor(); @NotNull PluginId getPluginId(); @@ -22,4 +26,7 @@ public interface PluginAwareClassLoader { long getLoadedClassCount(); @NotNull Collection getUrls(); + + @MagicConstant(intValues = {ACTIVE, UNLOAD_IN_PROGRESS}) + int getState(); } diff --git a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java index fb3a0268ac0b..2b9a491903c9 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java @@ -3,6 +3,7 @@ package com.intellij.openapi.extensions.impl; import com.intellij.diagnostic.ActivityCategory; import com.intellij.diagnostic.StartUpMeasurer; +import com.intellij.ide.plugins.cl.PluginAwareClassLoader; import com.intellij.openapi.Disposable; import com.intellij.openapi.components.ComponentManager; import com.intellij.openapi.diagnostic.Logger; @@ -465,6 +466,9 @@ public abstract class ExtensionPointImpl<@NotNull T> implements ExtensionPointadapter in one thread, adapter->EP in the other thread) private synchronized @Nullable T processAdapter(@NotNull ExtensionComponentAdapter adapter) { try { + if (!checkThatClassloaderIsActive(adapter)) { + return null; + } return adapter.createInstance(componentManager); } catch (ExtensionNotApplicableException ignore) { @@ -488,6 +492,10 @@ public abstract class ExtensionPointImpl<@NotNull T> implements ExtensionPoint extensionClassForCheck, @NotNull List adapters) { try { + if (!checkThatClassloaderIsActive(adapter)) { + return null; + } + boolean isNotifyThatAdded = listeners != null && listeners.length != 0 && !adapter.isInstanceCreated() && !isDynamic; // do not call CHECK_CANCELED here in loop because it is called by createInstance() T extension = adapter.createInstance(componentManager); @@ -526,6 +534,16 @@ public abstract class ExtensionPointImpl<@NotNull T> implements ExtensionPoint // must be before unloadPluginDescriptorNotRecursively as this method nullize classloader val classLoader = (subDescriptor ?: mainDescriptor).pluginClassLoader as? PluginClassLoader @@ -587,6 +592,11 @@ object DynamicPlugins { FUCounterUsageLogger.getInstance().logEvent("plugins.dynamic", eventId, fuData) } } + + if (!classLoaderUnloaded) { + setClassLoaderState(pluginDescriptor, PluginAwareClassLoader.ACTIVE) + } + return classLoaderUnloaded } @@ -1107,4 +1117,11 @@ private fun unloadClassLoader(pluginDescriptor: IdeaPluginDescriptorImpl, timeou val watcher = GCWatcher.tracking(pluginDescriptor.classLoader) ClassLoaderConfigurator.setPluginClassLoaderForMainAndSubPlugins(pluginDescriptor, null) return watcher.tryCollect(timeoutMs) +} + +private fun setClassLoaderState(pluginDescriptor: IdeaPluginDescriptorImpl, state: Int) { + (pluginDescriptor.classLoader as? PluginClassLoader)?.state = state + for (dependency in (pluginDescriptor.pluginDependencies ?: return)) { + dependency.subDescriptor?.let { setClassLoaderState(it, state) } + } } \ No newline at end of file