equal
deleted
inserted
replaced
198 * {@link #getSuppressedExceptions()}. |
198 * {@link #getSuppressedExceptions()}. |
199 * |
199 * |
200 * @serial |
200 * @serial |
201 * @since 1.7 |
201 * @since 1.7 |
202 */ |
202 */ |
203 private List<Throwable> suppressedExceptions = Collections.emptyList(); |
203 private List<Throwable> suppressedExceptions = null; |
|
204 /* |
|
205 * This field is lazily initialized when the first suppressed |
|
206 * exception is added. |
|
207 * |
|
208 * OutOfMemoryError is preallocated in the VM for better OOM |
|
209 * diagnosability during VM initialization. Constructor can't |
|
210 * be not invoked. If a new field to be added in the future must |
|
211 * be initialized to non-null, it requires a synchronized VM change. |
|
212 */ |
204 |
213 |
205 /** Message for trying to suppress a null exception. */ |
214 /** Message for trying to suppress a null exception. */ |
206 private static final String NULL_CAUSE_MESSAGE = "Cannot suppress a null exception."; |
215 private static final String NULL_CAUSE_MESSAGE = "Cannot suppress a null exception."; |
207 |
216 |
208 /** Caption for labeling causative exception stack traces */ |
217 /** Caption for labeling causative exception stack traces */ |
327 * |
336 * |
328 * @return the cause of this throwable or {@code null} if the |
337 * @return the cause of this throwable or {@code null} if the |
329 * cause is nonexistent or unknown. |
338 * cause is nonexistent or unknown. |
330 * @since 1.4 |
339 * @since 1.4 |
331 */ |
340 */ |
332 public Throwable getCause() { |
341 public synchronized Throwable getCause() { |
333 return (cause==this ? null : cause); |
342 return (cause==this ? null : cause); |
334 } |
343 } |
335 |
344 |
336 /** |
345 /** |
337 * Initializes the <i>cause</i> of this throwable to the specified value. |
346 * Initializes the <i>cause</i> of this throwable to the specified value. |
561 StackTraceElement[] trace = getOurStackTrace(); |
570 StackTraceElement[] trace = getOurStackTrace(); |
562 for (StackTraceElement traceElement : trace) |
571 for (StackTraceElement traceElement : trace) |
563 s.println("\tat " + traceElement); |
572 s.println("\tat " + traceElement); |
564 |
573 |
565 // Print suppressed exceptions, if any |
574 // Print suppressed exceptions, if any |
566 for (Throwable se : suppressedExceptions) |
575 for (Throwable se : getSuppressedExceptions()) |
567 se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu); |
576 se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu); |
568 |
577 |
569 // Print cause, if any |
578 // Print cause, if any |
570 Throwable ourCause = getCause(); |
579 Throwable ourCause = getCause(); |
571 if (ourCause != null) |
580 if (ourCause != null) |
602 s.println(prefix + "\tat " + trace[i]); |
611 s.println(prefix + "\tat " + trace[i]); |
603 if (framesInCommon != 0) |
612 if (framesInCommon != 0) |
604 s.println(prefix + "\t... " + framesInCommon + " more"); |
613 s.println(prefix + "\t... " + framesInCommon + " more"); |
605 |
614 |
606 // Print suppressed exceptions, if any |
615 // Print suppressed exceptions, if any |
607 for (Throwable se : suppressedExceptions) |
616 for (Throwable se : getSuppressedExceptions()) |
608 se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, |
617 se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, |
609 prefix +"\t", dejaVu); |
618 prefix +"\t", dejaVu); |
610 |
619 |
611 // Print cause, if any |
620 // Print cause, if any |
612 Throwable ourCause = getCause(); |
621 Throwable ourCause = getCause(); |
745 StackTraceElement[] defensiveCopy = stackTrace.clone(); |
754 StackTraceElement[] defensiveCopy = stackTrace.clone(); |
746 for (int i = 0; i < defensiveCopy.length; i++) |
755 for (int i = 0; i < defensiveCopy.length; i++) |
747 if (defensiveCopy[i] == null) |
756 if (defensiveCopy[i] == null) |
748 throw new NullPointerException("stackTrace[" + i + "]"); |
757 throw new NullPointerException("stackTrace[" + i + "]"); |
749 |
758 |
750 this.stackTrace = defensiveCopy; |
759 synchronized (this) { |
|
760 this.stackTrace = defensiveCopy; |
|
761 } |
751 } |
762 } |
752 |
763 |
753 /** |
764 /** |
754 * Returns the number of elements in the stack trace (or 0 if the stack |
765 * Returns the number of elements in the stack trace (or 0 if the stack |
755 * trace is unavailable). |
766 * trace is unavailable). |
770 native StackTraceElement getStackTraceElement(int index); |
781 native StackTraceElement getStackTraceElement(int index); |
771 |
782 |
772 private void readObject(ObjectInputStream s) |
783 private void readObject(ObjectInputStream s) |
773 throws IOException, ClassNotFoundException { |
784 throws IOException, ClassNotFoundException { |
774 s.defaultReadObject(); // read in all fields |
785 s.defaultReadObject(); // read in all fields |
775 List<Throwable> suppressed = Collections.emptyList(); |
786 List<Throwable> suppressed = null; |
776 if (suppressedExceptions != null && |
787 if (suppressedExceptions != null && |
777 !suppressedExceptions.isEmpty()) { // Copy Throwables to new list |
788 !suppressedExceptions.isEmpty()) { // Copy Throwables to new list |
778 suppressed = new ArrayList<Throwable>(); |
789 suppressed = new ArrayList<Throwable>(); |
779 for(Throwable t : suppressedExceptions) { |
790 for (Throwable t : suppressedExceptions) { |
780 if (t == null) |
791 if (t == null) |
781 throw new NullPointerException(NULL_CAUSE_MESSAGE); |
792 throw new NullPointerException(NULL_CAUSE_MESSAGE); |
782 suppressed.add(t); |
793 suppressed.add(t); |
783 } |
794 } |
784 } |
795 } |
817 if (exception == null) |
828 if (exception == null) |
818 throw new NullPointerException(NULL_CAUSE_MESSAGE); |
829 throw new NullPointerException(NULL_CAUSE_MESSAGE); |
819 if (exception == this) |
830 if (exception == this) |
820 throw new IllegalArgumentException("Self-suppression not permitted"); |
831 throw new IllegalArgumentException("Self-suppression not permitted"); |
821 |
832 |
822 if (suppressedExceptions.size() == 0) |
833 if (suppressedExceptions == null) |
823 suppressedExceptions = new ArrayList<Throwable>(); |
834 suppressedExceptions = new ArrayList<Throwable>(); |
824 suppressedExceptions.add(exception); |
835 suppressedExceptions.add(exception); |
825 } |
836 } |
826 |
837 |
827 private static final Throwable[] EMPTY_THROWABLE_ARRAY = new Throwable[0]; |
838 private static final Throwable[] EMPTY_THROWABLE_ARRAY = new Throwable[0]; |
833 * |
844 * |
834 * @return an array containing all of the exceptions that were |
845 * @return an array containing all of the exceptions that were |
835 * suppressed to deliver this exception. |
846 * suppressed to deliver this exception. |
836 * @since 1.7 |
847 * @since 1.7 |
837 */ |
848 */ |
838 public Throwable[] getSuppressedExceptions() { |
849 public synchronized Throwable[] getSuppressedExceptions() { |
839 return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY); |
850 if (suppressedExceptions == null) |
|
851 return EMPTY_THROWABLE_ARRAY; |
|
852 else |
|
853 return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY); |
840 } |
854 } |
841 } |
855 } |