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

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


   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang;
  27 import  java.io.*;
  28 import  java.util.*;

  29 
  30 /**
  31  * The {@code Throwable} class is the superclass of all errors and
  32  * exceptions in the Java language. Only objects that are instances of this
  33  * class (or one of its subclasses) are thrown by the Java Virtual Machine or
  34  * can be thrown by the Java {@code throw} statement. Similarly, only
  35  * this class or one of its subclasses can be the argument type in a
  36  * {@code catch} clause.
  37  *
  38  * For the purposes of compile-time checking of exceptions, {@code
  39  * Throwable} and any subclass of {@code Throwable} that is not also a
  40  * subclass of either {@link RuntimeException} or {@link Error} are
  41  * regarded as checked exceptions.
  42  *
  43  * <p>Instances of two subclasses, {@link java.lang.Error} and
  44  * {@link java.lang.Exception}, are conventionally used to indicate
  45  * that exceptional situations have occurred. Typically, these instances
  46  * are freshly created in the context of the exceptional situation so
  47  * as to include relevant information (such as stack trace data).
  48  *


 623      * Exception in thread "main" java.lang.Exception: Main block
 624      *  at Foo4.main(Foo4.java:6)
 625      *  Suppressed: Resource2$CloseFailException: Resource ID = 1
 626      *          at Resource2.close(Resource2.java:20)
 627      *          at Foo4.main(Foo4.java:5)
 628      *  Caused by: java.lang.Exception: Rats, you caught me
 629      *          at Resource2$CloseFailException.&lt;init&gt;(Resource2.java:45)
 630      *          ... 2 more
 631      * </pre>
 632      */
 633     public void printStackTrace() {
 634         printStackTrace(System.err);
 635     }
 636 
 637     /**
 638      * Prints this throwable and its backtrace to the specified print stream.
 639      *
 640      * @param s {@code PrintStream} to use for output
 641      */
 642     public void printStackTrace(PrintStream s) {
 643         printStackTrace(new WrappedPrintStream(s));
 644     }
 645 
 646     private void printStackTrace(PrintStreamOrWriter s) {













 647         // Guard against malicious overrides of Throwable.equals by
 648         // using a Set with identity equality semantics.
 649         Set<Throwable> dejaVu = Collections.newSetFromMap(new IdentityHashMap<>());
 650         dejaVu.add(this);
 651 
 652         synchronized (s.lock()) {
 653             // Print our stack trace
 654             s.println(this);
 655             StackTraceElement[] trace = getOurStackTrace();
 656             for (StackTraceElement traceElement : trace)
 657                 s.println("\tat " + traceElement);
 658 
 659             // Print suppressed exceptions, if any
 660             for (Throwable se : getSuppressed())
 661                 se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu);
 662 
 663             // Print cause, if any
 664             Throwable ourCause = getCause();
 665             if (ourCause != null)
 666                 ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu);
 667         }
 668     }
 669 
 670     /**
 671      * Print our stack trace as an enclosed exception for the specified
 672      * stack trace.
 673      */
 674     private void printEnclosedStackTrace(PrintStreamOrWriter s,
 675                                          StackTraceElement[] enclosingTrace,
 676                                          String caption,
 677                                          String prefix,
 678                                          Set<Throwable> dejaVu) {
 679         assert Thread.holdsLock(s.lock());

 680         if (dejaVu.contains(this)) {
 681             s.println("\t[CIRCULAR REFERENCE:" + this + "]");
 682         } else {
 683             dejaVu.add(this);
 684             // Compute number of frames in common between this and enclosing trace
 685             StackTraceElement[] trace = getOurStackTrace();
 686             int m = trace.length - 1;
 687             int n = enclosingTrace.length - 1;
 688             while (m >= 0 && n >=0 && trace[m].equals(enclosingTrace[n])) {
 689                 m--; n--;
 690             }
 691             int framesInCommon = trace.length - 1 - m;
 692 
 693             // Print our stack trace
 694             s.println(prefix + caption + this);
 695             for (int i = 0; i <= m; i++)
 696                 s.println(prefix + "\tat " + trace[i]);
 697             if (framesInCommon != 0)
 698                 s.println(prefix + "\t... " + framesInCommon + " more");
 699 
 700             // Print suppressed exceptions, if any
 701             for (Throwable se : getSuppressed())
 702                 se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION,
 703                                            prefix +"\t", dejaVu);
 704 
 705             // Print cause, if any
 706             Throwable ourCause = getCause();
 707             if (ourCause != null)
 708                 ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, prefix, dejaVu);
 709         }
 710     }
 711 
 712     /**
 713      * Prints this throwable and its backtrace to the specified
 714      * print writer.
 715      *
 716      * @param s {@code PrintWriter} to use for output
 717      * @since   1.1
 718      */
 719     public void printStackTrace(PrintWriter s) {
 720         printStackTrace(new WrappedPrintWriter(s));
 721     }
 722 
 723     /**
 724      * Wrapper class for PrintStream and PrintWriter to enable a single
 725      * implementation of printStackTrace.
 726      */
 727     private abstract static class PrintStreamOrWriter {
 728         /** Returns the object to be locked when using this StreamOrWriter */
 729         abstract Object lock();
 730 
 731         /** Prints the specified string as a line on this StreamOrWriter */
 732         abstract void println(Object o);
 733     }
 734 
 735     private static class WrappedPrintStream extends PrintStreamOrWriter {
 736         private final PrintStream printStream;
 737 
 738         WrappedPrintStream(PrintStream printStream) {
 739             this.printStream = printStream;
 740         }
 741 
 742         Object lock() {
 743             return printStream;
 744         }
 745 
 746         void println(Object o) {
 747             printStream.println(o);
 748         }
 749     }
 750 
 751     private static class WrappedPrintWriter extends PrintStreamOrWriter {
 752         private final PrintWriter printWriter;
 753 
 754         WrappedPrintWriter(PrintWriter printWriter) {
 755             this.printWriter = printWriter;
 756         }
 757 
 758         Object lock() {
 759             return printWriter;
 760         }
 761 
 762         void println(Object o) {
 763             printWriter.println(o);
 764         }
 765     }
 766 
 767     /**
 768      * Fills in the execution stack trace. This method records within this
 769      * {@code Throwable} object information about the current state of
 770      * the stack frames for the current thread.
 771      *
 772      * <p>If the stack trace of this {@code Throwable} {@linkplain
 773      * Throwable#Throwable(String, Throwable, boolean, boolean) is not
 774      * writable}, calling this method has no effect.
 775      *
 776      * @return  a reference to this {@code Throwable} instance.
 777      * @see     java.lang.Throwable#printStackTrace()
 778      */
 779     public synchronized Throwable fillInStackTrace() {
 780         if (stackTrace != null ||
 781             backtrace != null /* Out of protocol state */ ) {
 782             fillInStackTrace(0);
 783             stackTrace = UNASSIGNED_STACK;
 784         }




   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang;
  27 import  java.io.*;
  28 import  java.util.*;
  29 import java.util.function.Consumer;
  30 
  31 /**
  32  * The {@code Throwable} class is the superclass of all errors and
  33  * exceptions in the Java language. Only objects that are instances of this
  34  * class (or one of its subclasses) are thrown by the Java Virtual Machine or
  35  * can be thrown by the Java {@code throw} statement. Similarly, only
  36  * this class or one of its subclasses can be the argument type in a
  37  * {@code catch} clause.
  38  *
  39  * For the purposes of compile-time checking of exceptions, {@code
  40  * Throwable} and any subclass of {@code Throwable} that is not also a
  41  * subclass of either {@link RuntimeException} or {@link Error} are
  42  * regarded as checked exceptions.
  43  *
  44  * <p>Instances of two subclasses, {@link java.lang.Error} and
  45  * {@link java.lang.Exception}, are conventionally used to indicate
  46  * that exceptional situations have occurred. Typically, these instances
  47  * are freshly created in the context of the exceptional situation so
  48  * as to include relevant information (such as stack trace data).
  49  *


 624      * Exception in thread "main" java.lang.Exception: Main block
 625      *  at Foo4.main(Foo4.java:6)
 626      *  Suppressed: Resource2$CloseFailException: Resource ID = 1
 627      *          at Resource2.close(Resource2.java:20)
 628      *          at Foo4.main(Foo4.java:5)
 629      *  Caused by: java.lang.Exception: Rats, you caught me
 630      *          at Resource2$CloseFailException.&lt;init&gt;(Resource2.java:45)
 631      *          ... 2 more
 632      * </pre>
 633      */
 634     public void printStackTrace() {
 635         printStackTrace(System.err);
 636     }
 637 
 638     /**
 639      * Prints this throwable and its backtrace to the specified print stream.
 640      *
 641      * @param s {@code PrintStream} to use for output
 642      */
 643     public void printStackTrace(PrintStream s) {
 644         printStackTrace(s::println, s);
 645     }
 646 
 647     /**
 648      * Returns string representation of this throwable and its backtrace.
 649      *
 650      * @return string representation of this {@code Throwable} and its backtrace
 651      * @since   1.9
 652      */
 653     public String getStackTraceString() {
 654         final StringBuilder sb = new StringBuilder();
 655         printStackTrace(line -> sb.append(line).append(System.lineSeparator()), sb);
 656 
 657         return sb.toString();
 658     }
 659 
 660     private void printStackTrace(Consumer<String> s, Object lock) {
 661         // Guard against malicious overrides of Throwable.equals by
 662         // using a Set with identity equality semantics.
 663         Set<Throwable> dejaVu = Collections.newSetFromMap(new IdentityHashMap<>());
 664         dejaVu.add(this);
 665 
 666         synchronized (lock) {
 667             // Print our stack trace
 668             s.accept(toString());
 669             StackTraceElement[] trace = getOurStackTrace();
 670             for (StackTraceElement traceElement : trace)
 671                 s.accept("\tat " + traceElement);
 672 
 673             // Print suppressed exceptions, if any
 674             for (Throwable se : getSuppressed())
 675                 se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu, lock);
 676 
 677             // Print cause, if any
 678             Throwable ourCause = getCause();
 679             if (ourCause != null)
 680                 ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu, lock);
 681         }
 682     }
 683 
 684     /**
 685      * Print our stack trace as an enclosed exception for the specified
 686      * stack trace.
 687      */
 688     private void printEnclosedStackTrace(Consumer<String> s,
 689                                          StackTraceElement[] enclosingTrace,
 690                                          String caption,
 691                                          String prefix,
 692                                          Set<Throwable> dejaVu,
 693                                          Object lock) {
 694         assert Thread.holdsLock(lock);
 695         if (dejaVu.contains(this)) {
 696             s.accept("\t[CIRCULAR REFERENCE:" + this + "]");
 697         } else {
 698             dejaVu.add(this);
 699             // Compute number of frames in common between this and enclosing trace
 700             StackTraceElement[] trace = getOurStackTrace();
 701             int m = trace.length - 1;
 702             int n = enclosingTrace.length - 1;
 703             while (m >= 0 && n >=0 && trace[m].equals(enclosingTrace[n])) {
 704                 m--; n--;
 705             }
 706             int framesInCommon = trace.length - 1 - m;
 707 
 708             // Print our stack trace
 709             s.accept(prefix + caption + this);
 710             for (int i = 0; i <= m; i++)
 711                 s.accept(prefix + "\tat " + trace[i]);
 712             if (framesInCommon != 0)
 713                 s.accept(prefix + "\t... " + framesInCommon + " more");
 714 
 715             // Print suppressed exceptions, if any
 716             for (Throwable se : getSuppressed())
 717                 se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION,
 718                                            prefix +"\t", dejaVu, lock);
 719 
 720             // Print cause, if any
 721             Throwable ourCause = getCause();
 722             if (ourCause != null)
 723                 ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, prefix, dejaVu, lock);
 724         }
 725     }
 726 
 727     /**
 728      * Prints this throwable and its backtrace to the specified
 729      * print writer.
 730      *
 731      * @param s {@code PrintWriter} to use for output
 732      * @since   1.1
 733      */
 734     public void printStackTrace(PrintWriter s) {
 735         printStackTrace(s::println, s);












































 736     }
 737 
 738     /**
 739      * Fills in the execution stack trace. This method records within this
 740      * {@code Throwable} object information about the current state of
 741      * the stack frames for the current thread.
 742      *
 743      * <p>If the stack trace of this {@code Throwable} {@linkplain
 744      * Throwable#Throwable(String, Throwable, boolean, boolean) is not
 745      * writable}, calling this method has no effect.
 746      *
 747      * @return  a reference to this {@code Throwable} instance.
 748      * @see     java.lang.Throwable#printStackTrace()
 749      */
 750     public synchronized Throwable fillInStackTrace() {
 751         if (stackTrace != null ||
 752             backtrace != null /* Out of protocol state */ ) {
 753             fillInStackTrace(0);
 754             stackTrace = UNASSIGNED_STACK;
 755         }