String (@NotNull String fullThreadDump, @NotNull String exceptionType) { // We know that the AWT-EventQueue-* thread is dumped out first (see #sort above), and for each thread, there are at the very least // 3 lines printed out before the stack trace. If we don't see any of this, then return early List<String> threadDump = Arrays.asList(fullThreadDump.split("\n")); if (threadDump.size() < 3) { return null; } String line = threadDump.get(0); // e.g. "AWT-EventQueue-0 ... int i = line.indexOf(' '); if (i <= 1) { return null; } StringBuilder sb = new StringBuilder(200); sb.append(exceptionType).append(": "); sb.append(line, 1, i); // append thread name (e.g. AWT-EventQueue-0) line = threadDump.get(1); // e.g. " java.lang.Thread.State: RUNNABLE" String[] words = line.trim().split(" "); if (words.length < 2) { return null; } sb.append(' '); sb.append(words[1]); // e.g. "RUNNABLE" // the 3rd line contains lock information (or is empty) line = threadDump.get(2); if (!line.trim().isEmpty()) { sb.append(' '); sb.append(line.trim()); } sb.append('\n'); // the rest of the lines correspond to the stack trace until we reach an empty line for (i = 3; i < threadDump.size(); i++) { line = threadDump.get(i); if (line.trim().isEmpty()) { break; } sb.append(line); sb.append('\n'); } return sb.toString().trim(); }