From db50a48ebe25ebcc52bee2b933202c5a59779fb4 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 7 Oct 2019 20:16:54 +0200 Subject: [PATCH] Registry option to capture memory snapshot when plugin unload fails GitOrigin-RevId: 2bbbc7ab043e2efc58d4734e3ceecd153d144c57 --- .../intellij/ide/plugins/DynamicPlugins.kt | 19 ++++++++++++++++++- .../util/resources/misc/registry.properties | 3 +++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/DynamicPlugins.kt b/platform/platform-impl/src/com/intellij/ide/plugins/DynamicPlugins.kt index 26c7a35563e0..66b8b09005f1 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/DynamicPlugins.kt +++ b/platform/platform-impl/src/com/intellij/ide/plugins/DynamicPlugins.kt @@ -2,6 +2,9 @@ package com.intellij.ide.plugins import com.intellij.ide.ui.UIThemeProvider +import com.intellij.notification.NotificationDisplayType +import com.intellij.notification.NotificationGroup +import com.intellij.notification.NotificationType import com.intellij.openapi.Disposable import com.intellij.openapi.actionSystem.ActionManager import com.intellij.openapi.actionSystem.impl.ActionManagerImpl @@ -14,8 +17,13 @@ import com.intellij.openapi.extensions.impl.ExtensionsAreaImpl import com.intellij.openapi.project.ProjectManager import com.intellij.openapi.project.impl.ProjectImpl import com.intellij.openapi.util.IconLoader +import com.intellij.openapi.util.registry.Registry +import com.intellij.util.MemoryDumpHelper import com.intellij.util.ReflectionUtil +import com.intellij.util.SystemProperties import com.intellij.util.messages.Topic +import java.text.SimpleDateFormat +import java.util.* interface DynamicPluginListener { @JvmDefault @@ -33,6 +41,7 @@ interface DynamicPluginListener { object DynamicPlugins { private val LOG = Logger.getInstance(DynamicPlugins::class.java) + private val GROUP = NotificationGroup("Profiling", NotificationDisplayType.BALLOON, false) @JvmStatic fun allowLoadUnloadWithoutRestart(pluginDescriptor: IdeaPluginDescriptorImpl): Boolean { @@ -144,7 +153,15 @@ object DynamicPlugins { } } - return loadedPluginDescriptor.unloadClassLoader() + val classLoaderUnloaded = loadedPluginDescriptor.unloadClassLoader() + if (!classLoaderUnloaded && Registry.`is`("ide.plugins.snapshot.on.unload.fail") && MemoryDumpHelper.memoryDumpAvailable()) { + val snapshotFolder = System.getProperty("snapshots.path", SystemProperties.getUserHome()) + val snapshotDate = SimpleDateFormat("dd.MM.yyyy_HH.mm.ss").format(Date()) + val snapshotPath = "$snapshotFolder/unload-${pluginDescriptor.pluginId}-$snapshotDate.hprof" + MemoryDumpHelper.captureMemoryDump(snapshotPath) + GROUP.createNotification("Captured memory snapshot on plugin unload fail: $snapshotPath", NotificationType.WARNING).notify(null) + } + return classLoaderUnloaded } @JvmStatic diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 1a0c53235611..d0e9d4b8b6cb 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -1785,4 +1785,7 @@ contrast.scrollbars.alpha.level.description=Alpha level for contrast scrollbars ide.background.post.startup.activity.delay=5000 ide.background.post.startup.activity.delay.description=Delay in milliseconds between the end of normal IDE startup and the start of executing background post-startup activities +ide.plugins.snapshot.on.unload.fail=false +ide.plugins.snapshot.on.unload.fail.description=Capture memory snapshot when unloading a plugin without restart fails + # TODO please use EP com.intellij.registryKey for plugin/product specific keys \ No newline at end of file