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

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


 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.<init>(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);


 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;




 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 PrintStreamStackTracePrinter(s));
 644     }
 645 
 646     /**
 647      * Returns string representation of this throwable and its backtrace.
 648      *
 649      * @return string representation of this {@code Throwable} and its backtrace
 650      * @since   1.9
 651      */
 652     public String getStackTraceString() {
 653         final StringBuilder sb = new StringBuilder();
 654         printStackTrace(new StringBuilderStackTracePrinter(sb));
 655 
 656         return sb.toString();
 657     }
 658 
 659     private void printStackTrace(StackTracePrinter s) {
 660         // Guard against malicious overrides of Throwable.equals by
 661         // using a Set with identity equality semantics.
 662         Set<Throwable> dejaVu = Collections.newSetFromMap(new IdentityHashMap<>());
 663         dejaVu.add(this);
 664 
 665         synchronized (s.lock()) {
 666             // Print our stack trace
 667             s.println(this);
 668             StackTraceElement[] trace = getOurStackTrace();
 669             for (StackTraceElement traceElement : trace)
 670                 s.println("\tat " + traceElement);
 671 
 672             // Print suppressed exceptions, if any
 673             for (Throwable se : getSuppressed())
 674                 se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu);
 675 
 676             // Print cause, if any
 677             Throwable ourCause = getCause();
 678             if (ourCause != null)
 679                 ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu);
 680         }
 681     }
 682 
 683     /**
 684      * Print our stack trace as an enclosed exception for the specified
 685      * stack trace.
 686      */
 687     private void printEnclosedStackTrace(StackTracePrinter s,
 688                                          StackTraceElement[] enclosingTrace,
 689                                          String caption,
 690                                          String prefix,
 691                                          Set<Throwable> dejaVu) {
 692         assert Thread.holdsLock(s.lock());
 693         if (dejaVu.contains(this)) {
 694             s.println("\t[CIRCULAR REFERENCE:" + this + "]");
 695         } else {
 696             dejaVu.add(this);
 697             // Compute number of frames in common between this and enclosing trace
 698             StackTraceElement[] trace = getOurStackTrace();
 699             int m = trace.length - 1;
 700             int n = enclosingTrace.length - 1;
 701             while (m >= 0 && n >=0 && trace[m].equals(enclosingTrace[n])) {
 702                 m--; n--;
 703             }
 704             int framesInCommon = trace.length - 1 - m;
 705 
 706             // Print our stack trace
 707             s.println(prefix + caption + this);


 713             // Print suppressed exceptions, if any
 714             for (Throwable se : getSuppressed())
 715                 se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION,
 716                                            prefix +"\t", dejaVu);
 717 
 718             // Print cause, if any
 719             Throwable ourCause = getCause();
 720             if (ourCause != null)
 721                 ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, prefix, dejaVu);
 722         }
 723     }
 724 
 725     /**
 726      * Prints this throwable and its backtrace to the specified
 727      * print writer.
 728      *
 729      * @param s {@code PrintWriter} to use for output
 730      * @since   1.1
 731      */
 732     public void printStackTrace(PrintWriter s) {
 733         printStackTrace(new PrintWriterStackTracePrinter(s));
 734     }
 735 
 736     /**
 737      * Wrapper class of all targets for printing the stack trace to enable a single
 738      * implementation of that functionality.
 739      */
 740     private abstract static class StackTracePrinter {
 741         /** Returns the object to be locked when using this StackTracePrinter */
 742         abstract Object lock();
 743 
 744         /** Prints the specified string as a line on this StackTracePrinter */
 745         abstract void println(Object o);
 746     }
 747 
 748     private static class PrintStreamStackTracePrinter extends StackTracePrinter {
 749         private final PrintStream printStream;
 750 
 751         PrintStreamStackTracePrinter(PrintStream printStream) {
 752             this.printStream = printStream;
 753         }
 754 
 755         Object lock() {
 756             return printStream;
 757         }
 758 
 759         void println(Object o) {
 760             printStream.println(o);
 761         }
 762     }
 763 
 764     private static class PrintWriterStackTracePrinter extends StackTracePrinter {
 765         private final PrintWriter printWriter;
 766 
 767         PrintWriterStackTracePrinter(PrintWriter printWriter) {
 768             this.printWriter = printWriter;
 769         }
 770 
 771         Object lock() {
 772             return printWriter;
 773         }
 774 
 775         void println(Object o) {
 776             printWriter.println(o);
 777         }
 778     }
 779 
 780     private static class StringBuilderStackTracePrinter extends StackTracePrinter {
 781 
 782         private final StringBuilder builder;
 783 
 784         StringBuilderStackTracePrinter(StringBuilder builder) {
 785             this.builder = builder;
 786         }
 787 
 788         @Override
 789         Object lock() {
 790             return builder;
 791         }
 792 
 793         @Override
 794         void println(Object o) {
 795             builder.append(o).append(System.lineSeparator());
 796         }
 797     }
 798 
 799     /**
 800      * Fills in the execution stack trace. This method records within this
 801      * {@code Throwable} object information about the current state of
 802      * the stack frames for the current thread.
 803      *
 804      * <p>If the stack trace of this {@code Throwable} {@linkplain
 805      * Throwable#Throwable(String, Throwable, boolean, boolean) is not
 806      * writable}, calling this method has no effect.
 807      *
 808      * @return  a reference to this {@code Throwable} instance.
 809      * @see     java.lang.Throwable#printStackTrace()
 810      */
 811     public synchronized Throwable fillInStackTrace() {
 812         if (stackTrace != null ||
 813             backtrace != null /* Out of protocol state */ ) {
 814             fillInStackTrace(0);
 815             stackTrace = UNASSIGNED_STACK;