src/java.base/share/classes/java/lang/Throwable.java

Print this page
rev 11099 : 5050783: Added getStackTraceString method to Throwable class

*** 24,33 **** --- 24,34 ---- */ package java.lang; import java.io.*; import java.util.*; + import java.util.function.Consumer; /** * The {@code Throwable} class is the superclass of all errors and * exceptions in the Java language. Only objects that are instances of this * class (or one of its subclasses) are thrown by the Java Virtual Machine or
*** 638,686 **** * Prints this throwable and its backtrace to the specified print stream. * * @param s {@code PrintStream} to use for output */ public void printStackTrace(PrintStream s) { ! printStackTrace(new WrappedPrintStream(s)); } ! private void printStackTrace(PrintStreamOrWriter s) { // Guard against malicious overrides of Throwable.equals by // using a Set with identity equality semantics. Set<Throwable> dejaVu = Collections.newSetFromMap(new IdentityHashMap<>()); dejaVu.add(this); ! synchronized (s.lock()) { // Print our stack trace ! s.println(this); StackTraceElement[] trace = getOurStackTrace(); for (StackTraceElement traceElement : trace) ! s.println("\tat " + traceElement); // Print suppressed exceptions, if any for (Throwable se : getSuppressed()) ! se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu); // Print cause, if any Throwable ourCause = getCause(); if (ourCause != null) ! ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu); } } /** * Print our stack trace as an enclosed exception for the specified * stack trace. */ ! private void printEnclosedStackTrace(PrintStreamOrWriter s, StackTraceElement[] enclosingTrace, String caption, String prefix, ! Set<Throwable> dejaVu) { ! assert Thread.holdsLock(s.lock()); if (dejaVu.contains(this)) { ! s.println("\t[CIRCULAR REFERENCE:" + this + "]"); } else { dejaVu.add(this); // Compute number of frames in common between this and enclosing trace StackTraceElement[] trace = getOurStackTrace(); int m = trace.length - 1; --- 639,701 ---- * Prints this throwable and its backtrace to the specified print stream. * * @param s {@code PrintStream} to use for output */ public void printStackTrace(PrintStream s) { ! printStackTrace(s::println, s); } ! /** ! * Returns string representation of this throwable and its backtrace. ! * ! * @return string representation of this {@code Throwable} and its backtrace ! * @since 1.9 ! */ ! public String getStackTraceString() { ! final StringBuilder sb = new StringBuilder(); ! printStackTrace(line -> sb.append(line).append(System.lineSeparator()), sb); ! ! return sb.toString(); ! } ! ! private void printStackTrace(Consumer<String> s, Object lock) { // Guard against malicious overrides of Throwable.equals by // using a Set with identity equality semantics. Set<Throwable> dejaVu = Collections.newSetFromMap(new IdentityHashMap<>()); dejaVu.add(this); ! synchronized (lock) { // Print our stack trace ! s.accept(toString()); StackTraceElement[] trace = getOurStackTrace(); for (StackTraceElement traceElement : trace) ! s.accept("\tat " + traceElement); // Print suppressed exceptions, if any for (Throwable se : getSuppressed()) ! se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu, lock); // Print cause, if any Throwable ourCause = getCause(); if (ourCause != null) ! ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu, lock); } } /** * Print our stack trace as an enclosed exception for the specified * stack trace. */ ! private void printEnclosedStackTrace(Consumer<String> s, StackTraceElement[] enclosingTrace, String caption, String prefix, ! Set<Throwable> dejaVu, ! Object lock) { ! assert Thread.holdsLock(lock); if (dejaVu.contains(this)) { ! s.accept("\t[CIRCULAR REFERENCE:" + this + "]"); } else { dejaVu.add(this); // Compute number of frames in common between this and enclosing trace StackTraceElement[] trace = getOurStackTrace(); int m = trace.length - 1;
*** 689,713 **** m--; n--; } int framesInCommon = trace.length - 1 - m; // Print our stack trace ! s.println(prefix + caption + this); for (int i = 0; i <= m; i++) ! s.println(prefix + "\tat " + trace[i]); if (framesInCommon != 0) ! s.println(prefix + "\t... " + framesInCommon + " more"); // Print suppressed exceptions, if any for (Throwable se : getSuppressed()) se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, ! prefix +"\t", dejaVu); // Print cause, if any Throwable ourCause = getCause(); if (ourCause != null) ! ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, prefix, dejaVu); } } /** * Prints this throwable and its backtrace to the specified --- 704,728 ---- m--; n--; } int framesInCommon = trace.length - 1 - m; // Print our stack trace ! s.accept(prefix + caption + this); for (int i = 0; i <= m; i++) ! s.accept(prefix + "\tat " + trace[i]); if (framesInCommon != 0) ! s.accept(prefix + "\t... " + framesInCommon + " more"); // Print suppressed exceptions, if any for (Throwable se : getSuppressed()) se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, ! prefix +"\t", dejaVu, lock); // Print cause, if any Throwable ourCause = getCause(); if (ourCause != null) ! ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, prefix, dejaVu, lock); } } /** * Prints this throwable and its backtrace to the specified
*** 715,769 **** * * @param s {@code PrintWriter} to use for output * @since 1.1 */ public void printStackTrace(PrintWriter s) { ! printStackTrace(new WrappedPrintWriter(s)); ! } ! ! /** ! * Wrapper class for PrintStream and PrintWriter to enable a single ! * implementation of printStackTrace. ! */ ! private abstract static class PrintStreamOrWriter { ! /** Returns the object to be locked when using this StreamOrWriter */ ! abstract Object lock(); ! ! /** Prints the specified string as a line on this StreamOrWriter */ ! abstract void println(Object o); ! } ! ! private static class WrappedPrintStream extends PrintStreamOrWriter { ! private final PrintStream printStream; ! ! WrappedPrintStream(PrintStream printStream) { ! this.printStream = printStream; ! } ! ! Object lock() { ! return printStream; ! } ! ! void println(Object o) { ! printStream.println(o); ! } ! } ! ! private static class WrappedPrintWriter extends PrintStreamOrWriter { ! private final PrintWriter printWriter; ! ! WrappedPrintWriter(PrintWriter printWriter) { ! this.printWriter = printWriter; ! } ! ! Object lock() { ! return printWriter; ! } ! ! void println(Object o) { ! printWriter.println(o); ! } } /** * Fills in the execution stack trace. This method records within this * {@code Throwable} object information about the current state of --- 730,740 ---- * * @param s {@code PrintWriter} to use for output * @since 1.1 */ public void printStackTrace(PrintWriter s) { ! printStackTrace(s::println, s); } /** * Fills in the execution stack trace. This method records within this * {@code Throwable} object information about the current state of