mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
default java runner: thread dump action to show results in ThreadDumpPanel, with navigation to code and parsed into separate threads
VERY much needed when running JUnit tests again and again and things are complicated, to check for deadlocks etc ! now is turned on only when -Didea.java.run.wise.thread.dump=true
This commit is contained in:
@@ -21,6 +21,7 @@ import com.intellij.execution.ExecutionResult;
|
||||
import com.intellij.execution.Executor;
|
||||
import com.intellij.execution.configurations.*;
|
||||
import com.intellij.execution.executors.DefaultRunExecutor;
|
||||
import com.intellij.execution.process.CapturingProcessAdapter;
|
||||
import com.intellij.execution.process.ProcessAdapter;
|
||||
import com.intellij.execution.process.ProcessEvent;
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
@@ -28,23 +29,30 @@ import com.intellij.execution.runners.*;
|
||||
import com.intellij.execution.ui.ExecutionConsole;
|
||||
import com.intellij.execution.ui.RunContentDescriptor;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CustomShortcutSet;
|
||||
import com.intellij.openapi.actionSystem.Presentation;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.unscramble.AnalyzeStacktraceUtil;
|
||||
import com.intellij.unscramble.ThreadDumpConsoleFactory;
|
||||
import com.intellij.unscramble.ThreadDumpParser;
|
||||
import com.intellij.unscramble.ThreadState;
|
||||
import com.intellij.util.text.DateFormatUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author spleaner
|
||||
*/
|
||||
public class DefaultJavaProgramRunner extends JavaPatchableProgramRunner {
|
||||
private final static String ourWiseThreadDumpProperty = "idea.java.run.wise.thread.dump";
|
||||
|
||||
@Override
|
||||
public boolean canRun(@NotNull final String executorId, @NotNull final RunProfile profile) {
|
||||
return executorId.equals(DefaultRunExecutor.EXECUTOR_ID) &&
|
||||
@@ -166,11 +174,78 @@ public class DefaultJavaProgramRunner extends JavaPatchableProgramRunner {
|
||||
public void actionPerformed(final AnActionEvent e) {
|
||||
ProcessProxy proxy = ProcessProxyFactory.getInstance().getAttachedProxy(myProcessHandler);
|
||||
if (proxy != null) {
|
||||
final WiseDumpThreadsListener wiseListener = Boolean.TRUE.equals(Boolean.getBoolean(ourWiseThreadDumpProperty)) ?
|
||||
new WiseDumpThreadsListener(PlatformDataKeys.PROJECT.getData(e.getDataContext()), myProcessHandler) : null;
|
||||
|
||||
proxy.sendBreak();
|
||||
|
||||
if (wiseListener != null) {
|
||||
wiseListener.after();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class WiseDumpThreadsListener {
|
||||
private final Project myProject;
|
||||
private final ProcessHandler myProcessHandler;
|
||||
private final CapturingProcessAdapter myListener;
|
||||
|
||||
public WiseDumpThreadsListener(final Project project, final ProcessHandler processHandler) {
|
||||
myProject = project;
|
||||
myProcessHandler = processHandler;
|
||||
|
||||
myListener = new CapturingProcessAdapter();
|
||||
myProcessHandler.addProcessListener(myListener);
|
||||
}
|
||||
|
||||
public void after() {
|
||||
if (myProject == null) {
|
||||
myProcessHandler.removeProcessListener(myListener);
|
||||
return;
|
||||
}
|
||||
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (myProcessHandler.isProcessTerminated() || myProcessHandler.isProcessTerminating()) return;
|
||||
List<ThreadState> threadStates = null;
|
||||
final long start = System.currentTimeMillis();
|
||||
while ((System.currentTimeMillis() - start) < 1000) {
|
||||
final String stdout = myListener.getOutput().getStdout();
|
||||
threadStates = ThreadDumpParser.parse(stdout);
|
||||
if (threadStates == null || threadStates.isEmpty()) {
|
||||
try {
|
||||
Thread.sleep(50);
|
||||
}
|
||||
catch (InterruptedException e1) {
|
||||
//
|
||||
}
|
||||
threadStates = null;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
myProcessHandler.removeProcessListener(myListener);
|
||||
if (threadStates != null && ! threadStates.isEmpty()) {
|
||||
showThreadDump(myListener.getOutput().getStdout(), threadStates);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private void showThreadDump(final String out, final List<ThreadState> threadStates) {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
AnalyzeStacktraceUtil.addConsole(myProject, threadStates.size() > 1 ?
|
||||
new ThreadDumpConsoleFactory(myProject, threadStates) : null,
|
||||
"<Stacktrace> " + DateFormatUtil.formatDateTime(System.currentTimeMillis()), out);
|
||||
}
|
||||
}, ModalityState.NON_MODAL);
|
||||
}
|
||||
}
|
||||
|
||||
protected static class SoftExitAction extends LauncherBasedAction {
|
||||
public SoftExitAction(final ProcessHandler processHandler) {
|
||||
super(ExecutionBundle.message("run.configuration.exit.action.name"), null, AllIcons.Actions.Exit, processHandler);
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.unscramble;
|
||||
|
||||
import com.intellij.execution.ui.ConsoleView;
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import com.intellij.openapi.project.Project;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Irina.Chernushina on 7/13/13.
|
||||
*/
|
||||
public class ThreadDumpConsoleFactory implements AnalyzeStacktraceUtil.ConsoleFactory {
|
||||
private final Project myProject;
|
||||
private final List<ThreadState> myThreadDump;
|
||||
|
||||
public ThreadDumpConsoleFactory(Project project, List<ThreadState> threadDump) {
|
||||
myProject = project;
|
||||
myThreadDump = threadDump;
|
||||
}
|
||||
|
||||
public JComponent createConsoleComponent(ConsoleView consoleView, DefaultActionGroup toolbarActions) {
|
||||
return new ThreadDumpPanel(myProject, consoleView, toolbarActions, myThreadDump);
|
||||
}
|
||||
}
|
||||
@@ -15,12 +15,10 @@
|
||||
*/
|
||||
package com.intellij.unscramble;
|
||||
|
||||
import com.intellij.execution.ui.ConsoleView;
|
||||
import com.intellij.execution.ui.RunContentDescriptor;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.IdeBundle;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.fileChooser.FileChooser;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
|
||||
@@ -410,11 +408,7 @@ public class UnscrambleDialog extends DialogWrapper {
|
||||
message = IdeBundle.message("unscramble.unscrambled.deadlock.tab");
|
||||
icon = AllIcons.Debugger.KillProcess;
|
||||
}
|
||||
return AnalyzeStacktraceUtil.addConsole(project, threadDump.size() > 1 ? new AnalyzeStacktraceUtil.ConsoleFactory() {
|
||||
public JComponent createConsoleComponent(ConsoleView consoleView, DefaultActionGroup toolbarActions) {
|
||||
return new ThreadDumpPanel(project, consoleView, toolbarActions, threadDump);
|
||||
}
|
||||
} : null, message, unscrambledTrace, icon);
|
||||
return AnalyzeStacktraceUtil.addConsole(project, threadDump.size() > 1 ? new ThreadDumpConsoleFactory(project, threadDump) : null, message, unscrambledTrace, icon);
|
||||
}
|
||||
|
||||
protected String getDimensionServiceKey(){
|
||||
|
||||
Reference in New Issue
Block a user