diff --git a/java/java-tests/testSrc/com/intellij/psi/impl/file/impl/PsiEventsTest.java b/java/java-tests/testSrc/com/intellij/psi/impl/file/impl/PsiEventsTest.java index 80d29dba1f32..7545347e3584 100644 --- a/java/java-tests/testSrc/com/intellij/psi/impl/file/impl/PsiEventsTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/impl/file/impl/PsiEventsTest.java @@ -35,6 +35,7 @@ import com.intellij.testFramework.LeakHunter; import com.intellij.testFramework.PlatformTestUtil; import com.intellij.testFramework.PsiTestCase; import com.intellij.testFramework.PsiTestUtil; +import com.intellij.util.MemoryDumpHelper; import com.intellij.util.Processor; import com.intellij.util.WaitFor; import com.intellij.util.io.ReadOnlyAttributeUtil; @@ -199,6 +200,7 @@ public class PsiEventsTest extends PsiTestCase { LeakHunter.checkLeak(ApplicationManager.getApplication(), PsiDirectory.class, isReallyLeak); LeakHunter.checkLeak(IdeEventQueue.getInstance(), PsiDirectory.class, isReallyLeak); LeakHunter.checkLeak(LaterInvocator.getLaterInvocatorQueue(), PsiDirectory.class, isReallyLeak); + MemoryDumpHelper.captureMemoryDump("testRenameFileWithoutDir.hprof"); assertNull(((FileManagerImpl)fileManager).getCachedDirectory(myPrjDir1)); fail("directory just died"); } diff --git a/platform/util/src/com/intellij/util/MemoryDumpHelper.java b/platform/util/src/com/intellij/util/MemoryDumpHelper.java new file mode 100644 index 000000000000..d198fe9a4a9a --- /dev/null +++ b/platform/util/src/com/intellij/util/MemoryDumpHelper.java @@ -0,0 +1,76 @@ +package com.intellij.util; + +import com.intellij.openapi.diagnostic.Logger; +import org.jetbrains.annotations.NotNull; + +import javax.management.MBeanServer; +import javax.management.ObjectName; +import java.lang.management.ManagementFactory; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedExceptionAction; +import java.util.Iterator; +import java.util.Set; + +/** + * @author Pavel.Sher + */ +public class MemoryDumpHelper { + private static final String HOT_SPOT_BEAN_NAME = "com.sun.management:type=HotSpotDiagnostic"; + + private static final Object ourMXBean; + private static final Method ourDumpHeap; + + static { + Object mxBean; + Method dumpHeap; + + try { + final Class hotSpotMxBeanClass = Class.forName("com.sun.management.HotSpotDiagnosticMXBean"); + + mxBean = AccessController.doPrivileged(new PrivilegedExceptionAction() { + public Object run() throws Exception { + MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + Set s = server.queryNames(new ObjectName(HOT_SPOT_BEAN_NAME), null); + Iterator itr = s.iterator(); + if (itr.hasNext()) { + ObjectName name = itr.next(); + return ManagementFactory.newPlatformMXBeanProxy(server, name.toString(), hotSpotMxBeanClass); + } + else { + return null; + } + } + }); + + dumpHeap = mxBean.getClass().getMethod("dumpHeap", String.class, boolean.class); + } + catch (Throwable t) { + Logger.getInstance("#com.intellij.util.MemoryDumpHelper").info(t.getMessage()); + mxBean = null; + dumpHeap = null; + } + + ourMXBean = mxBean; + ourDumpHeap = dumpHeap; + } + + public static boolean memoryDumpAvailable() { + try { + return ourMXBean != null; + } + catch (UnsupportedOperationException e) { + return false; + } + } + + public static synchronized void captureMemoryDump(@NotNull String dumpPath) throws Exception { + ourDumpHeap.invoke(ourMXBean, dumpPath, true); + } + + /** @deprecated use {@link #captureMemoryDump(String)} (to be removed in IDEA 15) */ + @SuppressWarnings({"UnusedDeclaration", "SpellCheckingInspection"}) + public static Object getHotspotMBean() { + return ourMXBean; + } +}