From fa7e4eeb1a07b8789992cd5db86c0c742594b3cc Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 27 Feb 2012 13:27:03 +0400 Subject: [PATCH] memleaks fixed + throw exception on leak --- .../debugger/engine/DebugProcessImpl.java | 13 ++++++++----- .../engine/DebuggerManagerThreadImpl.java | 19 +++++++++++-------- .../impl/DefaultJavaProgramRunner.java | 10 ++++++++++ .../testFramework/src/_LastInSuiteTest.java | 2 +- .../com/intellij/openapi/util/Disposer.java | 5 ++++- .../openapi/util/objectTree/ObjectTree.java | 4 +++- 6 files changed, 37 insertions(+), 16 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java index beb967fb699d..39f4c48872e1 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java @@ -60,6 +60,7 @@ import com.intellij.execution.process.ProcessOutputTypes; import com.intellij.execution.runners.ExecutionUtil; import com.intellij.execution.runners.ProgramRunner; import com.intellij.idea.ActionsBundle; +import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; @@ -147,7 +148,9 @@ public abstract class DebugProcessImpl implements DebugProcess { private boolean myIsFailed = false; protected DebuggerSession mySession; @Nullable protected MethodReturnValueWatcher myReturnValueWatcher; - private final Alarm myStatusUpdateAlarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD); + private final Disposable myDisposable = Disposer.newDisposable(); + private final Alarm myStatusUpdateAlarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD, myDisposable); + /** @noinspection FieldCanBeLocal*/ private volatile boolean myDebugProcessStarted = false; @@ -553,7 +556,7 @@ public abstract class DebugProcessImpl implements DebugProcess { String portString = myConnection.getAddress(); String hostString = myConnection.getHostName(); - if (hostString == null || hostString.length() == 0) { + if (hostString == null || hostString.isEmpty()) { //noinspection HardCodedStringLiteral hostString = "localhost"; } @@ -822,7 +825,7 @@ public abstract class DebugProcessImpl implements DebugProcess { buf.append(DebuggerBundle.message("error.cannot.open.debugger.port")).append(" : "); buf.append(e1.getClass().getName()).append(" "); final String localizedMessage = e1.getLocalizedMessage(); - if (localizedMessage != null && localizedMessage.length() > 0) { + if (localizedMessage != null && !localizedMessage.isEmpty()) { buf.append('"'); buf.append(localizedMessage); buf.append('"'); @@ -850,14 +853,14 @@ public abstract class DebugProcessImpl implements DebugProcess { public void dispose() { NodeRendererSettings.getInstance().removeListener(mySettingsListener); - Disposer.dispose(myStatusUpdateAlarm); + Disposer.dispose(myDisposable); } public DebuggerManagerThreadImpl getManagerThread() { if (myDebuggerManagerThread == null) { synchronized (this) { if (myDebuggerManagerThread == null) { - myDebuggerManagerThread = new DebuggerManagerThreadImpl(); + myDebuggerManagerThread = new DebuggerManagerThreadImpl(myDisposable); } } } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebuggerManagerThreadImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebuggerManagerThreadImpl.java index f5569d5bdb1f..35b86a7f1aff 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebuggerManagerThreadImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebuggerManagerThreadImpl.java @@ -21,11 +21,13 @@ import com.intellij.debugger.engine.managerThread.DebuggerCommand; import com.intellij.debugger.engine.managerThread.DebuggerManagerThread; import com.intellij.debugger.engine.managerThread.SuspendContextCommand; import com.intellij.debugger.impl.InvokeAndWaitThread; +import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.util.ProgressIndicatorListenerAdapter; import com.intellij.openapi.progress.util.ProgressWindowWithNotification; +import com.intellij.openapi.util.Disposer; import com.intellij.util.Alarm; import com.sun.jdi.VMDisconnectedException; import org.jetbrains.annotations.NotNull; @@ -34,19 +36,21 @@ import org.jetbrains.annotations.TestOnly; /** * @author lex */ -public class DebuggerManagerThreadImpl extends InvokeAndWaitThread implements DebuggerManagerThread { +public class DebuggerManagerThreadImpl extends InvokeAndWaitThread implements DebuggerManagerThread, Disposable { private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.engine.DebuggerManagerThreadImpl"); public static final int COMMAND_TIMEOUT = 3000; private static final int RESTART_TIMEOUT = 500; - DebuggerManagerThreadImpl() { - //noinspection HardCodedStringLiteral - super(); + DebuggerManagerThreadImpl(@NotNull Disposable parent) { + Disposer.register(parent, this); + } + + public void dispose() { } @TestOnly - public static DebuggerManagerThreadImpl createTestInstance() { - return new DebuggerManagerThreadImpl(); + public static DebuggerManagerThreadImpl createTestInstance(@NotNull Disposable parent) { + return new DebuggerManagerThreadImpl(parent); } public static boolean isManagerThread() { @@ -94,14 +98,13 @@ public class DebuggerManagerThreadImpl extends InvokeAndWaitThread { } @SuppressWarnings({"UseOfSystemOutOrSystemErr", "HardCodedStringLiteral"}) - public void assertIsEmpty() { + public void assertIsEmpty(boolean throwError) { boolean firstObject = true; for (T object : myRootObjects) { @@ -219,6 +219,8 @@ public final class ObjectTree { if (trace != null) { System.err.println("*** First seen at: "); trace.printStackTrace(); + if (throwError) throw new RuntimeException("Memory leak detected: " + object + " of class " + object.getClass() + +"\nSee the cause for the corresponding Disposer.register() stacktrace:\n",trace); } }