mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-16 22:51:17 +07:00
Extract threadDump parser to a separate module
GitOrigin-RevId: c9d9890c5bf10e57b0aa77bb8f5c9ca7451c723e
This commit is contained in:
committed by
intellij-monorepo-bot
parent
20c62c2d7e
commit
e3d0d48018
1
.idea/modules.xml
generated
1
.idea/modules.xml
generated
@@ -789,6 +789,7 @@
|
|||||||
<module fileurl="file://$PROJECT_DIR$/platform/testFramework/ui/intellij.platform.testFramework.ui.iml" filepath="$PROJECT_DIR$/platform/testFramework/ui/intellij.platform.testFramework.ui.iml" />
|
<module fileurl="file://$PROJECT_DIR$/platform/testFramework/ui/intellij.platform.testFramework.ui.iml" filepath="$PROJECT_DIR$/platform/testFramework/ui/intellij.platform.testFramework.ui.iml" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/platform/testRunner/intellij.platform.testRunner.iml" filepath="$PROJECT_DIR$/platform/testRunner/intellij.platform.testRunner.iml" />
|
<module fileurl="file://$PROJECT_DIR$/platform/testRunner/intellij.platform.testRunner.iml" filepath="$PROJECT_DIR$/platform/testRunner/intellij.platform.testRunner.iml" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/platform/platform-tests/intellij.platform.tests.iml" filepath="$PROJECT_DIR$/platform/platform-tests/intellij.platform.tests.iml" />
|
<module fileurl="file://$PROJECT_DIR$/platform/platform-tests/intellij.platform.tests.iml" filepath="$PROJECT_DIR$/platform/platform-tests/intellij.platform.tests.iml" />
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/platform/threadDumpParser/intellij.platform.threadDumpParser.iml" filepath="$PROJECT_DIR$/platform/threadDumpParser/intellij.platform.threadDumpParser.iml" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/platform/tips-of-the-day/intellij.platform.tips.iml" filepath="$PROJECT_DIR$/platform/tips-of-the-day/intellij.platform.tips.iml" />
|
<module fileurl="file://$PROJECT_DIR$/platform/tips-of-the-day/intellij.platform.tips.iml" filepath="$PROJECT_DIR$/platform/tips-of-the-day/intellij.platform.tips.iml" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/platform/tracing-ide/intellij.platform.tracing.ide.iml" filepath="$PROJECT_DIR$/platform/tracing-ide/intellij.platform.tracing.ide.iml" />
|
<module fileurl="file://$PROJECT_DIR$/platform/tracing-ide/intellij.platform.tracing.ide.iml" filepath="$PROJECT_DIR$/platform/tracing-ide/intellij.platform.tracing.ide.iml" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/platform/tracing/intellij.platform.tracing.rt.iml" filepath="$PROJECT_DIR$/platform/tracing/intellij.platform.tracing.rt.iml" />
|
<module fileurl="file://$PROJECT_DIR$/platform/tracing/intellij.platform.tracing.rt.iml" filepath="$PROJECT_DIR$/platform/tracing/intellij.platform.tracing.rt.iml" />
|
||||||
|
|||||||
@@ -79,6 +79,7 @@
|
|||||||
<orderEntry type="library" name="kotlinx-serialization-core" level="project" />
|
<orderEntry type="library" name="kotlinx-serialization-core" level="project" />
|
||||||
<orderEntry type="library" name="kotlinx-serialization-json" level="project" />
|
<orderEntry type="library" name="kotlinx-serialization-json" level="project" />
|
||||||
<orderEntry type="module" module-name="intellij.platform.util.coroutines" />
|
<orderEntry type="module" module-name="intellij.platform.util.coroutines" />
|
||||||
|
<orderEntry type="module" module-name="intellij.platform.threadDumpParser" />
|
||||||
</component>
|
</component>
|
||||||
<component name="copyright">
|
<component name="copyright">
|
||||||
<Base>
|
<Base>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import com.intellij.openapi.application.ApplicationManager;
|
|||||||
import com.intellij.openapi.application.ModalityState;
|
import com.intellij.openapi.application.ModalityState;
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
import com.intellij.unscramble.ThreadDumpPanel;
|
import com.intellij.unscramble.ThreadDumpPanel;
|
||||||
import com.intellij.unscramble.ThreadState;
|
import com.intellij.threadDumpParser.ThreadState;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ import com.intellij.openapi.application.ApplicationManager;
|
|||||||
import com.intellij.openapi.application.ModalityState;
|
import com.intellij.openapi.application.ModalityState;
|
||||||
import com.intellij.openapi.project.DumbAwareAction;
|
import com.intellij.openapi.project.DumbAwareAction;
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
import com.intellij.unscramble.ThreadDumpParser;
|
import com.intellij.threadDumpParser.ThreadDumpParser;
|
||||||
import com.intellij.unscramble.ThreadState;
|
import com.intellij.threadDumpParser.ThreadState;
|
||||||
import com.intellij.util.SmartList;
|
import com.intellij.util.SmartList;
|
||||||
import com.intellij.xdebugger.XDebugSession;
|
import com.intellij.xdebugger.XDebugSession;
|
||||||
import com.sun.jdi.*;
|
import com.sun.jdi.*;
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ import com.intellij.ui.classFilter.ClassFilter;
|
|||||||
import com.intellij.ui.content.Content;
|
import com.intellij.ui.content.Content;
|
||||||
import com.intellij.ui.viewModel.extraction.ToolWindowContentExtractor;
|
import com.intellij.ui.viewModel.extraction.ToolWindowContentExtractor;
|
||||||
import com.intellij.unscramble.ThreadDumpPanel;
|
import com.intellij.unscramble.ThreadDumpPanel;
|
||||||
import com.intellij.unscramble.ThreadState;
|
import com.intellij.threadDumpParser.ThreadState;
|
||||||
import com.intellij.util.DocumentUtil;
|
import com.intellij.util.DocumentUtil;
|
||||||
import com.intellij.util.SmartList;
|
import com.intellij.util.SmartList;
|
||||||
import com.intellij.util.ThreeState;
|
import com.intellij.util.ThreeState;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import com.intellij.openapi.progress.ProcessCanceledException;
|
|||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
import com.intellij.openapi.util.io.FileUtil;
|
import com.intellij.openapi.util.io.FileUtil;
|
||||||
import com.intellij.openapi.util.registry.Registry;
|
import com.intellij.openapi.util.registry.Registry;
|
||||||
import com.intellij.unscramble.ThreadState;
|
import com.intellij.threadDumpParser.ThreadState;
|
||||||
import com.intellij.util.concurrency.Semaphore;
|
import com.intellij.util.concurrency.Semaphore;
|
||||||
import com.intellij.util.ui.MessageCategory;
|
import com.intellij.util.ui.MessageCategory;
|
||||||
import com.intellij.xdebugger.XDebugSession;
|
import com.intellij.xdebugger.XDebugSession;
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
<orderEntry type="module" module-name="intellij.platform.core.ui" />
|
<orderEntry type="module" module-name="intellij.platform.core.ui" />
|
||||||
<orderEntry type="module" module-name="intellij.platform.ide.util.io.impl" />
|
<orderEntry type="module" module-name="intellij.platform.ide.util.io.impl" />
|
||||||
<orderEntry type="module" module-name="intellij.platform.util.jdom" />
|
<orderEntry type="module" module-name="intellij.platform.util.jdom" />
|
||||||
|
<orderEntry type="module" module-name="intellij.platform.threadDumpParser" />
|
||||||
</component>
|
</component>
|
||||||
<component name="copyright">
|
<component name="copyright">
|
||||||
<Base>
|
<Base>
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ import com.intellij.openapi.util.registry.Registry;
|
|||||||
import com.intellij.psi.search.GlobalSearchScope;
|
import com.intellij.psi.search.GlobalSearchScope;
|
||||||
import com.intellij.unscramble.AnalyzeStacktraceUtil;
|
import com.intellij.unscramble.AnalyzeStacktraceUtil;
|
||||||
import com.intellij.unscramble.ThreadDumpConsoleFactory;
|
import com.intellij.unscramble.ThreadDumpConsoleFactory;
|
||||||
import com.intellij.unscramble.ThreadDumpParser;
|
import com.intellij.threadDumpParser.ThreadDumpParser;
|
||||||
import com.intellij.unscramble.ThreadState;
|
import com.intellij.threadDumpParser.ThreadState;
|
||||||
import com.intellij.util.ArrayUtil;
|
import com.intellij.util.ArrayUtil;
|
||||||
import com.intellij.util.TimeoutUtil;
|
import com.intellij.util.TimeoutUtil;
|
||||||
import com.intellij.util.concurrency.AppExecutorUtil;
|
import com.intellij.util.concurrency.AppExecutorUtil;
|
||||||
|
|||||||
@@ -80,6 +80,7 @@
|
|||||||
<orderEntry type="module" module-name="intellij.platform.ide.impl" />
|
<orderEntry type="module" module-name="intellij.platform.ide.impl" />
|
||||||
<orderEntry type="module" module-name="intellij.platform.markdown.utils" />
|
<orderEntry type="module" module-name="intellij.platform.markdown.utils" />
|
||||||
<orderEntry type="library" name="jetbrains.markdown" level="project" />
|
<orderEntry type="library" name="jetbrains.markdown" level="project" />
|
||||||
|
<orderEntry type="module" module-name="intellij.platform.threadDumpParser" />
|
||||||
</component>
|
</component>
|
||||||
<component name="copyright">
|
<component name="copyright">
|
||||||
<Base>
|
<Base>
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.intellij.unscramble;
|
|||||||
import com.intellij.execution.ui.ConsoleView;
|
import com.intellij.execution.ui.ConsoleView;
|
||||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.threadDumpParser.ThreadState;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ import com.intellij.openapi.ui.Splitter;
|
|||||||
import com.intellij.openapi.util.text.StringUtil;
|
import com.intellij.openapi.util.text.StringUtil;
|
||||||
import com.intellij.openapi.vfs.VirtualFile;
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
import com.intellij.openapi.wm.IdeFocusManager;
|
import com.intellij.openapi.wm.IdeFocusManager;
|
||||||
|
import com.intellij.threadDumpParser.ThreadOperation;
|
||||||
|
import com.intellij.threadDumpParser.ThreadState;
|
||||||
import com.intellij.ui.*;
|
import com.intellij.ui.*;
|
||||||
import com.intellij.ui.components.JBList;
|
import com.intellij.ui.components.JBList;
|
||||||
import com.intellij.util.PlatformIcons;
|
import com.intellij.util.PlatformIcons;
|
||||||
|
|||||||
@@ -16,5 +16,6 @@
|
|||||||
<orderEntry type="module" module-name="intellij.platform.lang.impl" />
|
<orderEntry type="module" module-name="intellij.platform.lang.impl" />
|
||||||
<orderEntry type="module" module-name="intellij.platform.core.ui" />
|
<orderEntry type="module" module-name="intellij.platform.core.ui" />
|
||||||
<orderEntry type="module" module-name="intellij.java.impl" />
|
<orderEntry type="module" module-name="intellij.java.impl" />
|
||||||
|
<orderEntry type="module" module-name="intellij.platform.threadDumpParser" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
@@ -20,6 +20,8 @@ import com.intellij.openapi.util.registry.Registry;
|
|||||||
import com.intellij.openapi.util.text.StringUtil;
|
import com.intellij.openapi.util.text.StringUtil;
|
||||||
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
|
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
|
||||||
import com.intellij.openapi.vcs.configurable.VcsContentAnnotationConfigurable;
|
import com.intellij.openapi.vcs.configurable.VcsContentAnnotationConfigurable;
|
||||||
|
import com.intellij.threadDumpParser.ThreadDumpParser;
|
||||||
|
import com.intellij.threadDumpParser.ThreadState;
|
||||||
import com.intellij.ui.GuiUtils;
|
import com.intellij.ui.GuiUtils;
|
||||||
import com.intellij.ui.SimpleListCellRenderer;
|
import com.intellij.ui.SimpleListCellRenderer;
|
||||||
import com.intellij.ui.TextFieldWithHistory;
|
import com.intellij.ui.TextFieldWithHistory;
|
||||||
@@ -45,7 +47,6 @@ public class UnscrambleDialog extends DialogWrapper {
|
|||||||
private static final @NonNls String PROPERTY_LOG_FILE_LAST_URL = "UNSCRAMBLE_LOG_FILE_LAST_URL";
|
private static final @NonNls String PROPERTY_LOG_FILE_LAST_URL = "UNSCRAMBLE_LOG_FILE_LAST_URL";
|
||||||
private static final @NonNls String PROPERTY_UNSCRAMBLER_NAME_USED = "UNSCRAMBLER_NAME_USED";
|
private static final @NonNls String PROPERTY_UNSCRAMBLER_NAME_USED = "UNSCRAMBLER_NAME_USED";
|
||||||
private static final Condition<ThreadState> DEADLOCK_CONDITION = state -> state.isDeadlocked();
|
private static final Condition<ThreadState> DEADLOCK_CONDITION = state -> state.isDeadlocked();
|
||||||
private static final String[] IMPORTANT_THREAD_DUMP_WORDS = ContainerUtil.ar("tid", "nid", "wait", "parking", "prio", "os_prio", "java");
|
|
||||||
|
|
||||||
private final Project myProject;
|
private final Project myProject;
|
||||||
private JPanel myEditorPanel;
|
private JPanel myEditorPanel;
|
||||||
@@ -279,77 +280,10 @@ public class UnscrambleDialog extends DialogWrapper {
|
|||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e){
|
public void actionPerformed(ActionEvent e){
|
||||||
String text = myStacktraceEditorPanel.getText();
|
String text = myStacktraceEditorPanel.getText();
|
||||||
myStacktraceEditorPanel.setText(normalizeText(text));
|
myStacktraceEditorPanel.setText(ThreadDumpParser.normalizeText(text));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String normalizeText(@NonNls String text) {
|
|
||||||
StringBuilder builder = new StringBuilder(text.length());
|
|
||||||
|
|
||||||
text = text.replaceAll("(\\S[ \\t\\x0B\\f\\r]+)(at\\s+)", "$1\n$2");
|
|
||||||
text = text.replaceAll("(\\\\n|\\\\r|\\\\t)+(at\\s+)", "\n$2");
|
|
||||||
String[] lines = text.split("\n");
|
|
||||||
|
|
||||||
boolean first = true;
|
|
||||||
boolean inAuxInfo = false;
|
|
||||||
for (final String line : lines) {
|
|
||||||
//noinspection HardCodedStringLiteral
|
|
||||||
if (!inAuxInfo && (line.startsWith("JNI global references") || line.trim().equals("Heap"))) {
|
|
||||||
builder.append("\n");
|
|
||||||
inAuxInfo = true;
|
|
||||||
}
|
|
||||||
if (inAuxInfo) {
|
|
||||||
builder.append(trimSuffix(line)).append("\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (line.startsWith("at breakpoint")) { // possible thread status mixed with "at ..."
|
|
||||||
builder.append(" ").append(trimSuffix(line));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!first && (mustHaveNewLineBefore(line) || StringUtil.endsWith(builder, ")"))) {
|
|
||||||
if (!StringUtil.endsWith(builder, "\n")) builder.append("\n");
|
|
||||||
if (line.startsWith("\"")) builder.append("\n"); // Additional line break for thread names
|
|
||||||
}
|
|
||||||
first = false;
|
|
||||||
int i = builder.lastIndexOf("\n");
|
|
||||||
CharSequence lastLine = i == -1 ? builder : builder.subSequence(i + 1, builder.length());
|
|
||||||
if (!line.matches("\\s+.*") && lastLine.length() > 0) {
|
|
||||||
if (lastLine.toString().matches("\\s*at") //separate 'at' from filename
|
|
||||||
|| ContainerUtil.or(IMPORTANT_THREAD_DUMP_WORDS, word -> line.startsWith(word))) {
|
|
||||||
builder.append(" ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
builder.append(trimSuffix(line));
|
|
||||||
}
|
|
||||||
return builder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String trimSuffix(final String line) {
|
|
||||||
int len = line.length();
|
|
||||||
|
|
||||||
while ((0 < len) && (line.charAt(len-1) <= ' ')) {
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
return (len < line.length()) ? line.substring(0, len) : line;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean mustHaveNewLineBefore(String line) {
|
|
||||||
final int nonWs = CharArrayUtil.shiftForward(line, 0, " \t");
|
|
||||||
if (nonWs < line.length()) {
|
|
||||||
line = line.substring(nonWs);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line.startsWith("at")) return true; // Start of the new stack frame entry
|
|
||||||
if (line.startsWith("Caused")) return true; // Caused by message
|
|
||||||
if (line.startsWith("- locked")) return true; // "Locked a monitor" logging
|
|
||||||
if (line.startsWith("- waiting")) return true; // "Waiting for monitor" logging
|
|
||||||
if (line.startsWith("- parking to wait")) return true;
|
|
||||||
if (line.startsWith("java.lang.Thread.State")) return true;
|
|
||||||
if (line.startsWith("\"")) return true; // Start of the new thread (thread name)
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doOKAction() {
|
protected void doOKAction() {
|
||||||
if (myConfigurable != null && myConfigurable.isModified()) {
|
if (myConfigurable != null && myConfigurable.isModified()) {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import com.intellij.openapi.project.Project;
|
|||||||
import com.intellij.openapi.util.registry.Registry;
|
import com.intellij.openapi.util.registry.Registry;
|
||||||
import com.intellij.openapi.util.text.StringUtil;
|
import com.intellij.openapi.util.text.StringUtil;
|
||||||
import com.intellij.openapi.wm.IdeFrame;
|
import com.intellij.openapi.wm.IdeFrame;
|
||||||
|
import com.intellij.threadDumpParser.ThreadDumpParser;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@@ -35,7 +36,7 @@ class UnscrambleListener extends ClipboardAnalyzeListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canHandle(@NotNull String value) {
|
public boolean canHandle(@NotNull String value) {
|
||||||
value = UnscrambleDialog.normalizeText(value);
|
value = ThreadDumpParser.normalizeText(value);
|
||||||
int linesCount = 0;
|
int linesCount = 0;
|
||||||
for (String line : value.split("\n")) {
|
for (String line : value.split("\n")) {
|
||||||
line = line.trim();
|
line = line.trim();
|
||||||
|
|||||||
0
platform/threadDumpParser/api-dump.txt
Normal file
0
platform/threadDumpParser/api-dump.txt
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="JAVA_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||||
|
<exclude-output />
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/testSrc" isTestSource="true" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
<orderEntry type="library" name="kotlin-stdlib" level="project" />
|
||||||
|
<orderEntry type="module" module-name="intellij.platform.util" />
|
||||||
|
<orderEntry type="module" module-name="intellij.platform.ide.impl" />
|
||||||
|
<orderEntry type="library" scope="TEST" name="JUnit3" level="project" />
|
||||||
|
<orderEntry type="module" module-name="intellij.tools.ide.metrics.benchmark" scope="TEST" />
|
||||||
|
<orderEntry type="module" module-name="intellij.platform.testFramework" scope="TEST" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||||
package com.intellij.unscramble;
|
package com.intellij.threadDumpParser;
|
||||||
|
|
||||||
import com.intellij.diagnostic.EventCountDumper;
|
import com.intellij.diagnostic.EventCountDumper;
|
||||||
import com.intellij.openapi.util.text.StringUtil;
|
import com.intellij.openapi.util.text.StringUtil;
|
||||||
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
|
import com.intellij.util.text.CharArrayUtil;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
import org.jetbrains.annotations.NonNls;
|
import org.jetbrains.annotations.NonNls;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -14,7 +17,7 @@ import java.util.regex.Pattern;
|
|||||||
|
|
||||||
import static com.intellij.diagnostic.CoroutineDumperKt.isCoroutineDumpHeader;
|
import static com.intellij.diagnostic.CoroutineDumperKt.isCoroutineDumpHeader;
|
||||||
|
|
||||||
|
@ApiStatus.Internal
|
||||||
public final class ThreadDumpParser {
|
public final class ThreadDumpParser {
|
||||||
private static final Pattern ourThreadStartPattern = Pattern.compile("^\"(.+)\".+(prio=\\d+ (?:os_prio=[^\\s]+ )?.*tid=[^\\s]+ nid=[^\\s]+|[Ii][Dd]=\\d+) ([^\\[]+)");
|
private static final Pattern ourThreadStartPattern = Pattern.compile("^\"(.+)\".+(prio=\\d+ (?:os_prio=[^\\s]+ )?.*tid=[^\\s]+ nid=[^\\s]+|[Ii][Dd]=\\d+) ([^\\[]+)");
|
||||||
private static final Pattern ourForcedThreadStartPattern = Pattern.compile("^Thread (\\d+): \\(state = (.+)\\)");
|
private static final Pattern ourForcedThreadStartPattern = Pattern.compile("^Thread (\\d+): \\(state = (.+)\\)");
|
||||||
@@ -30,6 +33,8 @@ public final class ThreadDumpParser {
|
|||||||
private static final String AT_JAVA_LANG_OBJECT_WAIT = "at java.lang.Object.wait(";
|
private static final String AT_JAVA_LANG_OBJECT_WAIT = "at java.lang.Object.wait(";
|
||||||
private static final Pattern ourLockedOwnableSynchronizersPattern = Pattern.compile("- <(0x[\\da-f]+)> \\(.*\\)");
|
private static final Pattern ourLockedOwnableSynchronizersPattern = Pattern.compile("- <(0x[\\da-f]+)> \\(.*\\)");
|
||||||
|
|
||||||
|
private static final String[] IMPORTANT_THREAD_DUMP_WORDS = ContainerUtil.ar("tid", "nid", "wait", "parking", "prio", "os_prio", "java");
|
||||||
|
|
||||||
|
|
||||||
private ThreadDumpParser() {
|
private ThreadDumpParser() {
|
||||||
}
|
}
|
||||||
@@ -263,4 +268,72 @@ public final class ThreadDumpParser {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String normalizeText(@NonNls String text) {
|
||||||
|
StringBuilder builder = new StringBuilder(text.length());
|
||||||
|
|
||||||
|
text = text.replaceAll("(\\S[ \\t\\x0B\\f\\r]+)(at\\s+)", "$1\n$2");
|
||||||
|
text = text.replaceAll("(\\\\n|\\\\r|\\\\t)+(at\\s+)", "\n$2");
|
||||||
|
String[] lines = text.split("\n");
|
||||||
|
|
||||||
|
boolean first = true;
|
||||||
|
boolean inAuxInfo = false;
|
||||||
|
for (final String line : lines) {
|
||||||
|
//noinspection HardCodedStringLiteral
|
||||||
|
if (!inAuxInfo && (line.startsWith("JNI global references") || line.trim().equals("Heap"))) {
|
||||||
|
builder.append("\n");
|
||||||
|
inAuxInfo = true;
|
||||||
|
}
|
||||||
|
if (inAuxInfo) {
|
||||||
|
builder.append(trimSuffix(line)).append("\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (line.startsWith("at breakpoint")) { // possible thread status mixed with "at ..."
|
||||||
|
builder.append(" ").append(trimSuffix(line));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!first && (mustHaveNewLineBefore(line) || StringUtil.endsWith(builder, ")"))) {
|
||||||
|
if (!StringUtil.endsWith(builder, "\n")) builder.append("\n");
|
||||||
|
if (line.startsWith("\"")) builder.append("\n"); // Additional line break for thread names
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
int i = builder.lastIndexOf("\n");
|
||||||
|
CharSequence lastLine = i == -1 ? builder : builder.subSequence(i + 1, builder.length());
|
||||||
|
if (!line.matches("\\s+.*") && lastLine.length() > 0) {
|
||||||
|
if (lastLine.toString().matches("\\s*at") //separate 'at' from filename
|
||||||
|
|| ContainerUtil.or(IMPORTANT_THREAD_DUMP_WORDS, word -> line.startsWith(word))) {
|
||||||
|
builder.append(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
builder.append(trimSuffix(line));
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean mustHaveNewLineBefore(String line) {
|
||||||
|
final int nonWs = CharArrayUtil.shiftForward(line, 0, " \t");
|
||||||
|
if (nonWs < line.length()) {
|
||||||
|
line = line.substring(nonWs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line.startsWith("at")) return true; // Start of the new stack frame entry
|
||||||
|
if (line.startsWith("Caused")) return true; // Caused by message
|
||||||
|
if (line.startsWith("- locked")) return true; // "Locked a monitor" logging
|
||||||
|
if (line.startsWith("- waiting")) return true; // "Waiting for monitor" logging
|
||||||
|
if (line.startsWith("- parking to wait")) return true;
|
||||||
|
if (line.startsWith("java.lang.Thread.State")) return true;
|
||||||
|
if (line.startsWith("\"")) return true; // Start of the new thread (thread name)
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String trimSuffix(final String line) {
|
||||||
|
int len = line.length();
|
||||||
|
|
||||||
|
while ((0 < len) && (line.charAt(len - 1) <= ' ')) {
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
return (len < line.length()) ? line.substring(0, len) : line;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
package com.intellij.unscramble;
|
package com.intellij.threadDumpParser;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
|
@ApiStatus.Internal
|
||||||
public enum ThreadOperation {
|
public enum ThreadOperation {
|
||||||
Socket("socket operation"), IO("I/O");
|
Socket("socket operation"), IO("I/O");
|
||||||
|
|
||||||
@@ -1,17 +1,18 @@
|
|||||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||||
package com.intellij.unscramble;
|
package com.intellij.threadDumpParser;
|
||||||
|
|
||||||
import com.intellij.diagnostic.ThreadDumper;
|
import com.intellij.diagnostic.ThreadDumper;
|
||||||
import com.intellij.openapi.util.Comparing;
|
import com.intellij.openapi.util.Comparing;
|
||||||
import com.intellij.openapi.util.NlsSafe;
|
import com.intellij.openapi.util.NlsSafe;
|
||||||
import com.intellij.openapi.util.text.StringUtil;
|
import com.intellij.openapi.util.text.StringUtil;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
import org.jetbrains.annotations.NonNls;
|
import org.jetbrains.annotations.NonNls;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
@ApiStatus.Internal
|
||||||
public class ThreadState {
|
public class ThreadState {
|
||||||
private final String myName;
|
private final String myName;
|
||||||
private final String myState;
|
private final String myState;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||||
package com.intellij.unscramble;
|
package com.intellij.threadDumpParser;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
import org.jetbrains.annotations.NonNls;
|
import org.jetbrains.annotations.NonNls;
|
||||||
@@ -165,7 +165,7 @@ public class NormalizeTextTest extends TestCase {
|
|||||||
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
|
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
|
||||||
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
|
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
|
||||||
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)""");
|
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)""");
|
||||||
assertEquals(2, ThreadDumpParser.parse(UnscrambleDialog.normalizeText(text)).size());
|
assertEquals(2, ThreadDumpParser.parse(ThreadDumpParser.normalizeText(text)).size());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testJsonEscapes() {
|
public void testJsonEscapes() {
|
||||||
@@ -182,6 +182,6 @@ public class NormalizeTextTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void doTest(@NonNls String stackTrace, @NonNls String expected) {
|
private static void doTest(@NonNls String stackTrace, @NonNls String expected) {
|
||||||
assertEquals(expected, UnscrambleDialog.normalizeText(stackTrace));
|
assertEquals(expected, ThreadDumpParser.normalizeText(stackTrace));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||||
package com.intellij.unscramble;
|
package com.intellij.threadDumpParser;
|
||||||
|
|
||||||
import com.intellij.openapi.util.text.StringUtil;
|
import com.intellij.openapi.util.text.StringUtil;
|
||||||
import com.intellij.tools.ide.metrics.benchmark.Benchmark;
|
import com.intellij.tools.ide.metrics.benchmark.Benchmark;
|
||||||
Reference in New Issue
Block a user