mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
memleaks fixed + throw exception on leak
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<DebuggerCommandImpl> implements DebuggerManagerThread {
|
||||
public class DebuggerManagerThreadImpl extends InvokeAndWaitThread<DebuggerCommandImpl> 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<DebuggerComma
|
||||
* if worker thread is still processing the same command
|
||||
* calls terminateCommand
|
||||
*/
|
||||
|
||||
public void terminateAndInvoke(DebuggerCommandImpl command, int terminateTimeout) {
|
||||
final DebuggerCommandImpl currentCommand = myEvents.getCurrentEvent();
|
||||
|
||||
invoke(command);
|
||||
|
||||
if (currentCommand != null) {
|
||||
final Alarm alarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD);
|
||||
final Alarm alarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD, this);
|
||||
alarm.addRequest(new Runnable() {
|
||||
public void run() {
|
||||
if (currentCommand == myEvents.getCurrentEvent()) {
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.intellij.openapi.actionSystem.CustomShortcutSet;
|
||||
import com.intellij.openapi.actionSystem.Presentation;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -44,16 +45,19 @@ import java.awt.event.KeyEvent;
|
||||
* @author spleaner
|
||||
*/
|
||||
public class DefaultJavaProgramRunner extends JavaPatchableProgramRunner {
|
||||
@Override
|
||||
public boolean canRun(@NotNull final String executorId, @NotNull final RunProfile profile) {
|
||||
return executorId.equals(DefaultRunExecutor.EXECUTOR_ID) &&
|
||||
profile instanceof ModuleRunProfile &&
|
||||
!(profile instanceof RunConfigurationWithSuppressedDefaultRunAction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void patch(JavaParameters javaParameters, RunnerSettings settings, final boolean beforeExecution) throws ExecutionException {
|
||||
runCustomPatchers(javaParameters, settings, Executor.EXECUTOR_EXTENSION_NAME.findExtension(DefaultRunExecutor.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RunContentDescriptor doExecute(final Project project, final Executor executor, final RunProfileState state, final RunContentDescriptor contentToReuse,
|
||||
final ExecutionEnvironment env) throws ExecutionException {
|
||||
FileDocumentManager.getInstance().saveAllDocuments();
|
||||
@@ -83,6 +87,7 @@ public class DefaultJavaProgramRunner extends JavaPatchableProgramRunner {
|
||||
onProcessStarted(env.getRunnerSettings(), executionResult);
|
||||
|
||||
final RunContentBuilder contentBuilder = new RunContentBuilder(project, this, executor);
|
||||
Disposer.register(project, contentBuilder);
|
||||
contentBuilder.setExecutionResult(executionResult);
|
||||
contentBuilder.setEnvironment(env);
|
||||
if (shouldAddDefaultActions) {
|
||||
@@ -110,6 +115,7 @@ public class DefaultJavaProgramRunner extends JavaPatchableProgramRunner {
|
||||
final ProcessHandler processHandler = executionResult.getProcessHandler();
|
||||
assert processHandler != null : executionResult;
|
||||
processHandler.addProcessListener(new ProcessAdapter() {
|
||||
@Override
|
||||
public void processTerminated(final ProcessEvent event) {
|
||||
processHandler.removeProcessListener(this);
|
||||
controlBreakAction.unregisterCustomShortcutSet(consoleComponent);
|
||||
@@ -129,6 +135,7 @@ public class DefaultJavaProgramRunner extends JavaPatchableProgramRunner {
|
||||
myProcessHandler = processHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(final AnActionEvent event) {
|
||||
final Presentation presentation = event.getPresentation();
|
||||
if (!isVisible()) {
|
||||
@@ -157,6 +164,7 @@ public class DefaultJavaProgramRunner extends JavaPatchableProgramRunner {
|
||||
return super.isVisible() && ProcessProxyFactory.getInstance().isBreakGenLibraryAvailable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(final AnActionEvent e) {
|
||||
ProcessProxy proxy = ProcessProxyFactory.getInstance().getAttachedProxy(myProcessHandler);
|
||||
if (proxy != null) {
|
||||
@@ -170,6 +178,7 @@ public class DefaultJavaProgramRunner extends JavaPatchableProgramRunner {
|
||||
super(ExecutionBundle.message("run.configuration.exit.action.name"), null, IconLoader.getIcon("/actions/exit.png"), processHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(final AnActionEvent e) {
|
||||
ProcessProxy proxy = ProcessProxyFactory.getInstance().getAttachedProxy(myProcessHandler);
|
||||
if (proxy != null) {
|
||||
@@ -178,6 +187,7 @@ public class DefaultJavaProgramRunner extends JavaPatchableProgramRunner {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getRunnerId() {
|
||||
return "Run";
|
||||
|
||||
@@ -47,6 +47,6 @@ public class _LastInSuiteTest extends TestCase {
|
||||
});
|
||||
|
||||
LeakHunter.checkProjectLeak(application);
|
||||
Disposer.assertIsEmpty();
|
||||
Disposer.assertIsEmpty(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,8 +114,11 @@ public class Disposer {
|
||||
}
|
||||
|
||||
public static void assertIsEmpty() {
|
||||
assertIsEmpty(false);
|
||||
}
|
||||
public static void assertIsEmpty(boolean throwError) {
|
||||
if (ourDebugMode) {
|
||||
ourTree.assertIsEmpty();
|
||||
ourTree.assertIsEmpty(throwError);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -197,7 +197,7 @@ public final class ObjectTree<T> {
|
||||
}
|
||||
|
||||
@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<T> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user