112 * @since JDK1.0
113 */
114 public class Throwable implements Serializable {
115 /** use serialVersionUID from JDK 1.0.2 for interoperability */
116 private static final long serialVersionUID = -3042686055658047285L;
117
118 /**
119 * Native code saves some indication of the stack backtrace in this slot.
120 */
121 private transient Object backtrace;
122
123 /**
124 * Specific details about the Throwable. For example, for
125 * {@code FileNotFoundException}, this contains the name of
126 * the file that could not be found.
127 *
128 * @serial
129 */
130 private String detailMessage;
131
132 /**
133 * A shared value for an empty stack.
134 */
135 private static final StackTraceElement[] EMPTY_STACK = new StackTraceElement[0];
136
137 /*
138 * To allow Throwable objects to be made immutable and safely
139 * reused by the JVM, such as OutOfMemoryErrors, fields of
140 * Throwable that are writable in response to user actions, cause
141 * and suppressedExceptions obey the following protocol:
142 *
143 * 1) The fields are initialized to a non-null sentinel value
144 * which indicates the value has logically not been set.
145 *
146 * 2) Writing a null to the field indicates further writes
147 * are forbidden
148 *
149 * 3) The sentinel value may be replaced with another non-null
150 * value.
151 *
152 * For example, implementations of the HotSpot JVM have
153 * preallocated OutOfMemoryError objects to provide for better
154 * diagnosability of that situation. These objects are created
155 * without calling the constructor for that class and the fields
156 * in question are initialized to null. To support this
157 * capability, any new fields added to Throwable that require
158 * being initialized to a non-null value require a coordinated JVM
159 * change.
160 */
161
162 /**
163 * The throwable that caused this throwable to get thrown, or null if this
164 * throwable was not caused by another throwable, or if the causative
165 * throwable is unknown. If this field is equal to this throwable itself,
166 * it indicates that the cause of this throwable has not yet been
167 * initialized.
168 *
169 * @serial
170 * @since 1.4
171 */
172 private Throwable cause = this;
173
174 /**
175 * The stack trace, as returned by {@link #getStackTrace()}.
176 *
177 * @serial
178 * @since 1.4
179 */
180 private StackTraceElement[] stackTrace;
181
182 // Setting this static field introduces an acceptable
183 // initialization dependency on a few java.util classes.
184 private static final List<Throwable> SUPPRESSED_SENTINEL =
185 Collections.unmodifiableList(new ArrayList<Throwable>(0));
186
187 /**
188 * The list of suppressed exceptions, as returned by {@link
189 * #getSuppressed()}. The list is initialized to a zero-element
190 * unmodifiable sentinel list. When a serialized Throwable is
191 * read in, if the {@code suppressedExceptions} field points to a
192 * zero-element list, the field is reset to the sentinel value.
193 *
194 * @serial
195 * @since 1.7
196 */
197 private List<Throwable> suppressedExceptions = SUPPRESSED_SENTINEL;
198
199 /** Message for trying to suppress a null exception. */
200 private static final String NULL_CAUSE_MESSAGE = "Cannot suppress a null exception.";
267 * wrappers for other throwables (for example, {@link
268 * java.security.PrivilegedActionException}).
269 *
270 * <p>The {@link #fillInStackTrace()} method is called to initialize
271 * the stack trace data in the newly created throwable.
272 *
273 * @param cause the cause (which is saved for later retrieval by the
274 * {@link #getCause()} method). (A {@code null} value is
275 * permitted, and indicates that the cause is nonexistent or
276 * unknown.)
277 * @since 1.4
278 */
279 public Throwable(Throwable cause) {
280 fillInStackTrace();
281 detailMessage = (cause==null ? null : cause.toString());
282 this.cause = cause;
283 }
284
285 /**
286 * Constructs a new throwable with the specified detail message,
287 * cause, and {@linkplain #addSuppressed suppression} enabled or
288 * disabled. If suppression is disabled, {@link #getSuppressed}
289 * for this object will return a zero-length array and calls to
290 * {@link #addSuppressed} that would otherwise append an exception
291 * to the suppressed list will have no effect.
292 *
293 * <p>Note that the other constructors of {@code Throwable} treat
294 * suppression as being enabled. Subclasses of {@code Throwable}
295 * should document any conditions under which suppression is
296 * disabled. Disabling of suppression should only occur in
297 * exceptional circumstances where special requirements exist,
298 * such as a virtual machine reusing exception objects under
299 * low-memory situations.
300 *
301 * @param message the detail message.
302 * @param cause the cause. (A {@code null} value is permitted,
303 * and indicates that the cause is nonexistent or unknown.)
304 * @param enableSuppression whether or not suppression is enabled or disabled
305 *
306 * @see OutOfMemoryError
307 * @see NullPointerException
308 * @see ArithmeticException
309 * @since 1.7
310 */
311 protected Throwable(String message, Throwable cause,
312 boolean enableSuppression) {
313 fillInStackTrace();
314 detailMessage = message;
315 this.cause = cause;
316 if (!enableSuppression)
317 suppressedExceptions = null;
318 }
319
320 /**
321 * Returns the detail message string of this throwable.
322 *
323 * @return the detail message string of this {@code Throwable} instance
324 * (which may be {@code null}).
325 */
326 public String getMessage() {
327 return detailMessage;
328 }
329
330 /**
331 * Creates a localized description of this throwable.
332 * Subclasses may override this method in order to produce a
333 * locale-specific message. For subclasses that do not override this
690 private final PrintWriter printWriter;
691
692 WrappedPrintWriter(PrintWriter printWriter) {
693 this.printWriter = printWriter;
694 }
695
696 Object lock() {
697 return printWriter;
698 }
699
700 void println(Object o) {
701 printWriter.println(o);
702 }
703 }
704
705 /**
706 * Fills in the execution stack trace. This method records within this
707 * {@code Throwable} object information about the current state of
708 * the stack frames for the current thread.
709 *
710 * @return a reference to this {@code Throwable} instance.
711 * @see java.lang.Throwable#printStackTrace()
712 */
713 public synchronized native Throwable fillInStackTrace();
714
715 /**
716 * Provides programmatic access to the stack trace information printed by
717 * {@link #printStackTrace()}. Returns an array of stack trace elements,
718 * each representing one stack frame. The zeroth element of the array
719 * (assuming the array's length is non-zero) represents the top of the
720 * stack, which is the last method invocation in the sequence. Typically,
721 * this is the point at which this throwable was created and thrown.
722 * The last element of the array (assuming the array's length is non-zero)
723 * represents the bottom of the stack, which is the first method invocation
724 * in the sequence.
725 *
726 * <p>Some virtual machines may, under some circumstances, omit one
727 * or more stack frames from the stack trace. In the extreme case,
728 * a virtual machine that has no stack trace information concerning
729 * this throwable is permitted to return a zero-length array from this
730 * method. Generally speaking, the array returned by this method will
731 * contain one element for every frame that would be printed by
732 * {@code printStackTrace}.
733 *
734 * @return an array of stack trace elements representing the stack trace
735 * pertaining to this throwable.
736 * @since 1.4
737 */
738 public StackTraceElement[] getStackTrace() {
739 return getOurStackTrace().clone();
740 }
741
742 private synchronized StackTraceElement[] getOurStackTrace() {
743 // Initialize stack trace if this is the first call to this method
744 if (stackTrace == null) {
745 int depth = getStackTraceDepth();
746 stackTrace = new StackTraceElement[depth];
747 for (int i=0; i < depth; i++)
748 stackTrace[i] = getStackTraceElement(i);
749 }
750 return stackTrace;
751 }
752
753 /**
754 * Sets the stack trace elements that will be returned by
755 * {@link #getStackTrace()} and printed by {@link #printStackTrace()}
756 * and related methods.
757 *
758 * This method, which is designed for use by RPC frameworks and other
759 * advanced systems, allows the client to override the default
760 * stack trace that is either generated by {@link #fillInStackTrace()}
761 * when a throwable is constructed or deserialized when a throwable is
762 * read from a serialization stream.
763 *
764 * @param stackTrace the stack trace elements to be associated with
765 * this {@code Throwable}. The specified array is copied by this
766 * call; changes in the specified array after the method invocation
767 * returns will have no affect on this {@code Throwable}'s stack
768 * trace.
769 *
770 * @throws NullPointerException if {@code stackTrace} is
771 * {@code null}, or if any of the elements of
772 * {@code stackTrace} are {@code null}
773 *
774 * @since 1.4
775 */
776 public void setStackTrace(StackTraceElement[] stackTrace) {
777 StackTraceElement[] defensiveCopy = stackTrace.clone();
778 for (int i = 0; i < defensiveCopy.length; i++)
779 if (defensiveCopy[i] == null)
780 throw new NullPointerException("stackTrace[" + i + "]");
781
782 synchronized (this) {
783 this.stackTrace = defensiveCopy;
784 }
785 }
786
787 /**
788 * Returns the number of elements in the stack trace (or 0 if the stack
789 * trace is unavailable).
790 *
791 * package-protection for use by SharedSecrets.
792 */
793 native int getStackTraceDepth();
794
795 /**
796 * Returns the specified element of the stack trace.
797 *
798 * package-protection for use by SharedSecrets.
799 *
800 * @param index index of the element to return.
801 * @throws IndexOutOfBoundsException if {@code index < 0 ||
802 * index >= getStackTraceDepth() }
803 */
804 native StackTraceElement getStackTraceElement(int index);
805
806 /**
807 * Reads a {@code Throwable} from a stream, enforcing
808 * well-formedness constraints on fields. Null entries and
809 * self-pointers are not allowed in the list of {@code
810 * suppressedExceptions}. Null entries are not allowed for stack
811 * trace elements.
812 *
813 * Note that there are no constraints on the value the {@code
814 * cause} field can hold; both {@code null} and {@code this} are
815 * valid values for the field.
816 */
817 private void readObject(ObjectInputStream s)
818 throws IOException, ClassNotFoundException {
819 s.defaultReadObject(); // read in all fields
820 if (suppressedExceptions != null) {
821 List<Throwable> suppressed = null;
822 if (suppressedExceptions.isEmpty()) {
823 // Use the sentinel for a zero-length list
824 suppressed = SUPPRESSED_SENTINEL;
825 } else { // Copy Throwables to new list
826 suppressed = new ArrayList<>(1);
827 for (Throwable t : suppressedExceptions) {
828 // Enforce constraints on suppressed exceptions in
829 // case of corrupt or malicious stream.
830 if (t == null)
831 throw new NullPointerException(NULL_CAUSE_MESSAGE);
832 if (t == this)
833 throw new IllegalArgumentException(SELF_SUPPRESSION_MESSAGE);
834 suppressed.add(t);
835 }
836 }
837 suppressedExceptions = suppressed;
838 } // else a null suppressedExceptions field remains null
839
840 if (stackTrace != null) {
841 for (StackTraceElement ste : stackTrace) {
842 if (ste == null)
843 throw new NullPointerException("null StackTraceElement in serial stream. ");
844 }
845 } else {
846 // A null stackTrace field in the serial form can result from
847 // an exception serialized without that field in older JDK releases.
848 stackTrace = EMPTY_STACK;
849 }
850
851 }
852
853 /**
854 * Write a {@code Throwable} object to a stream.
855 */
856 private synchronized void writeObject(ObjectOutputStream s)
857 throws IOException {
858 getOurStackTrace(); // Ensure that stackTrace field is initialized.
859 s.defaultWriteObject();
860 }
861
862 /**
863 * Appends the specified exception to the exceptions that were
864 * suppressed in order to deliver this exception. This method is
865 * typically called (automatically and implicitly) by the {@code
866 * try}-with-resources statement.
867 *
868 * <p>The suppression behavior is enabled <em>unless</em> disabled
869 * {@linkplain #Throwable(String, Throwable, boolean) via a
870 * constructor}. When suppression is disabled, this method does
871 * nothing other than to validate its argument.
872 *
873 * <p>Note that when one exception {@linkplain
874 * #initCause(Throwable) causes} another exception, the first
875 * exception is usually caught and then the second exception is
876 * thrown in response. In other words, there is a causal
877 * connection between the two exceptions.
878 *
879 * In contrast, there are situations where two independent
916 if (exception == null)
917 throw new NullPointerException(NULL_CAUSE_MESSAGE);
918
919 if (suppressedExceptions == null) // Suppressed exceptions not recorded
920 return;
921
922 if (suppressedExceptions == SUPPRESSED_SENTINEL)
923 suppressedExceptions = new ArrayList<>(1);
924
925 suppressedExceptions.add(exception);
926 }
927
928 private static final Throwable[] EMPTY_THROWABLE_ARRAY = new Throwable[0];
929
930 /**
931 * Returns an array containing all of the exceptions that were
932 * suppressed, typically by the {@code try}-with-resources
933 * statement, in order to deliver this exception.
934 *
935 * If no exceptions were suppressed or {@linkplain
936 * Throwable(String, Throwable, boolean) suppression is disabled},
937 * an empty array is returned.
938 *
939 * @return an array containing all of the exceptions that were
940 * suppressed to deliver this exception.
941 * @since 1.7
942 */
943 public final synchronized Throwable[] getSuppressed() {
944 if (suppressedExceptions == SUPPRESSED_SENTINEL ||
945 suppressedExceptions == null)
946 return EMPTY_THROWABLE_ARRAY;
947 else
948 return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY);
949 }
950 }
|
112 * @since JDK1.0
113 */
114 public class Throwable implements Serializable {
115 /** use serialVersionUID from JDK 1.0.2 for interoperability */
116 private static final long serialVersionUID = -3042686055658047285L;
117
118 /**
119 * Native code saves some indication of the stack backtrace in this slot.
120 */
121 private transient Object backtrace;
122
123 /**
124 * Specific details about the Throwable. For example, for
125 * {@code FileNotFoundException}, this contains the name of
126 * the file that could not be found.
127 *
128 * @serial
129 */
130 private String detailMessage;
131
132
133 /**
134 * Holder class to defer initializing sentinel objects only used
135 * for serialization.
136 */
137 private static class SentinelHolder {
138 /**
139 * {@linkplain #setStackTrace(StackTraceElement[]) Setting the
140 * stack trace} to a one-element array containing this sentinel
141 * value indicates future attempts to set the stack trace will be
142 * ignored. The sentinal is equal to the result of calling:<br>
143 * {@code new StackTraceElement("", "", null, Integer.MIN_VALUE)}
144 */
145 public static final StackTraceElement STACK_TRACE_ELEMENT_SENTINEL =
146 new StackTraceElement("", "", null, Integer.MIN_VALUE);
147
148 /**
149 * Sentinel value used in the serial form to indicate an immutable
150 * stack trace.
151 */
152 public static final StackTraceElement[] STACK_TRACE_SENTINEL =
153 new StackTraceElement[] {STACK_TRACE_ELEMENT_SENTINEL};
154 }
155
156 /**
157 * A value indicating the stack trace field has not yet been initialized.
158 */
159 private static final StackTraceElement[] UNINITIALIZED_STACK =
160 new StackTraceElement[] {new StackTraceElement("UNINITIALIZED", "STACK", null, -1)};
161
162 /**
163 * A value indicating that the logical stack trace has been
164 * populated into the backtrace field.
165 */
166 private static final StackTraceElement[] FILLED_IN_STACK =
167 new StackTraceElement[] {new StackTraceElement("FILLED_IN", "STACK", null, -1)};
168
169 /**
170 * A shared value for an empty stack.
171 */
172 private static final StackTraceElement[] EMPTY_STACK = new StackTraceElement[0];
173
174 /*
175 * To allow Throwable objects to be made immutable and safely
176 * reused by the JVM, such as OutOfMemoryErrors, fields of
177 * Throwable that are writable in response to user actions, cause,
178 * stackTrace, and suppressedExceptions obey the following
179 * protocol:
180 *
181 * 1) The fields are initialized to a non-null sentinel value
182 * which indicates the value has logically not been set.
183 *
184 * 2) Writing a null to the field indicates further writes
185 * are forbidden
186 *
187 * 3) The sentinel value may be replaced with another non-null
188 * value.
189 *
190 * For example, implementations of the HotSpot JVM have
191 * preallocated OutOfMemoryError objects to provide for better
192 * diagnosability of that situation. These objects are created
193 * without calling the constructor for that class and the fields
194 * in question are initialized to null. To support this
195 * capability, any new fields added to Throwable that require
196 * being initialized to a non-null value require a coordinated JVM
197 * change.
198 */
199
200 /**
201 * The throwable that caused this throwable to get thrown, or null if this
202 * throwable was not caused by another throwable, or if the causative
203 * throwable is unknown. If this field is equal to this throwable itself,
204 * it indicates that the cause of this throwable has not yet been
205 * initialized.
206 *
207 * @serial
208 * @since 1.4
209 */
210 private Throwable cause = this;
211
212 /**
213 * The stack trace, as returned by {@link #getStackTrace()}.
214 *
215 * The field is initialized to a zero-length array. A {@code
216 * null} value of this field indicates subsequent calls to {@link
217 * #setStackTrace()} and {@link #fillInStackTrace} will be be no-ops.
218 *
219 * @serial
220 * @since 1.4
221 */
222 private StackTraceElement[] stackTrace = UNINITIALIZED_STACK;
223
224 // Setting this static field introduces an acceptable
225 // initialization dependency on a few java.util classes.
226 private static final List<Throwable> SUPPRESSED_SENTINEL =
227 Collections.unmodifiableList(new ArrayList<Throwable>(0));
228
229 /**
230 * The list of suppressed exceptions, as returned by {@link
231 * #getSuppressed()}. The list is initialized to a zero-element
232 * unmodifiable sentinel list. When a serialized Throwable is
233 * read in, if the {@code suppressedExceptions} field points to a
234 * zero-element list, the field is reset to the sentinel value.
235 *
236 * @serial
237 * @since 1.7
238 */
239 private List<Throwable> suppressedExceptions = SUPPRESSED_SENTINEL;
240
241 /** Message for trying to suppress a null exception. */
242 private static final String NULL_CAUSE_MESSAGE = "Cannot suppress a null exception.";
309 * wrappers for other throwables (for example, {@link
310 * java.security.PrivilegedActionException}).
311 *
312 * <p>The {@link #fillInStackTrace()} method is called to initialize
313 * the stack trace data in the newly created throwable.
314 *
315 * @param cause the cause (which is saved for later retrieval by the
316 * {@link #getCause()} method). (A {@code null} value is
317 * permitted, and indicates that the cause is nonexistent or
318 * unknown.)
319 * @since 1.4
320 */
321 public Throwable(Throwable cause) {
322 fillInStackTrace();
323 detailMessage = (cause==null ? null : cause.toString());
324 this.cause = cause;
325 }
326
327 /**
328 * Constructs a new throwable with the specified detail message,
329 * cause, {@linkplain #addSuppressed suppression} enabled or
330 * disabled, and writable stack trace enabled or disabled. If
331 * suppression is disabled, {@link #getSuppressed} for this object
332 * will return a zero-length array and calls to {@link
333 * #addSuppressed} that would otherwise append an exception to the
334 * suppressed list will have no effect. If the writable stack
335 * trace is false, this constructor will not call {@link
336 * #fillInStackTrace()} and subsequent calls to {@code
337 * fillInStackTrace} and {@link
338 * #setStackTrace(StackTraceElement[])} will not set the stack
339 * trace. If the writable stack trace is false, {@link
340 * #getStackTrace} will return a zero length array.
341 *
342 * <p>Note that the other constructors of {@code Throwable} treat
343 * suppression as being enabled and the stack trace as being
344 * writable. Subclasses of {@code Throwable} should document any
345 * conditions under which suppression is disabled. Disabling of
346 * suppression should only occur in exceptional circumstances
347 * where special requirements exist, such as a virtual machine
348 * reusing exception objects under low-memory situations.
349 *
350 * @param message the detail message.
351 * @param cause the cause. (A {@code null} value is permitted,
352 * and indicates that the cause is nonexistent or unknown.)
353 * @param enableSuppression whether or not suppression is enabled or disabled
354 * @param writableStackTrace whether or not the stack trace should be
355 * writable
356 *
357 * @see OutOfMemoryError
358 * @see NullPointerException
359 * @see ArithmeticException
360 * @since 1.7
361 */
362 protected Throwable(String message, Throwable cause,
363 boolean enableSuppression,
364 boolean writableStackTrace) {
365 if (writableStackTrace) {
366 fillInStackTrace();
367 } else {
368 stackTrace = null;
369 }
370 detailMessage = message;
371 this.cause = cause;
372 if (!enableSuppression)
373 suppressedExceptions = null;
374 }
375
376 /**
377 * Returns the detail message string of this throwable.
378 *
379 * @return the detail message string of this {@code Throwable} instance
380 * (which may be {@code null}).
381 */
382 public String getMessage() {
383 return detailMessage;
384 }
385
386 /**
387 * Creates a localized description of this throwable.
388 * Subclasses may override this method in order to produce a
389 * locale-specific message. For subclasses that do not override this
746 private final PrintWriter printWriter;
747
748 WrappedPrintWriter(PrintWriter printWriter) {
749 this.printWriter = printWriter;
750 }
751
752 Object lock() {
753 return printWriter;
754 }
755
756 void println(Object o) {
757 printWriter.println(o);
758 }
759 }
760
761 /**
762 * Fills in the execution stack trace. This method records within this
763 * {@code Throwable} object information about the current state of
764 * the stack frames for the current thread.
765 *
766 * <p>If the stack trace of this {@code Throwable} {@linkplain
767 * Throwable#Throwable(String, Throwable, boolean, boolean) is not
768 * writable}, calling this method has no effect.
769 *
770 * @return a reference to this {@code Throwable} instance.
771 * @see java.lang.Throwable#printStackTrace()
772 */
773 public synchronized Throwable fillInStackTrace() {
774 if (stackTrace != null) {
775 fillInStackTrace(0);
776 stackTrace = FILLED_IN_STACK;
777 }
778 return this;
779 }
780
781 private native Throwable fillInStackTrace(int dummy);
782
783 /**
784 * Provides programmatic access to the stack trace information printed by
785 * {@link #printStackTrace()}. Returns an array of stack trace elements,
786 * each representing one stack frame. The zeroth element of the array
787 * (assuming the array's length is non-zero) represents the top of the
788 * stack, which is the last method invocation in the sequence. Typically,
789 * this is the point at which this throwable was created and thrown.
790 * The last element of the array (assuming the array's length is non-zero)
791 * represents the bottom of the stack, which is the first method invocation
792 * in the sequence.
793 *
794 * <p>Some virtual machines may, under some circumstances, omit one
795 * or more stack frames from the stack trace. In the extreme case,
796 * a virtual machine that has no stack trace information concerning
797 * this throwable is permitted to return a zero-length array from this
798 * method. Generally speaking, the array returned by this method will
799 * contain one element for every frame that would be printed by
800 * {@code printStackTrace}.
801 *
802 * @return an array of stack trace elements representing the stack trace
803 * pertaining to this throwable.
804 * @since 1.4
805 */
806 public StackTraceElement[] getStackTrace() {
807 return getOurStackTrace().clone();
808 }
809
810 private synchronized StackTraceElement[] getOurStackTrace() {
811 // Initialize stack trace field with information from
812 // backtrace if this is the first call to this method
813 if (stackTrace == FILLED_IN_STACK) {
814 int depth = getStackTraceDepth();
815 stackTrace = new StackTraceElement[depth];
816 for (int i=0; i < depth; i++)
817 stackTrace[i] = getStackTraceElement(i);
818 } else if (stackTrace == null) {
819 return EMPTY_STACK;
820 }
821 return stackTrace;
822 }
823
824 /**
825 * Sets the stack trace elements that will be returned by
826 * {@link #getStackTrace()} and printed by {@link #printStackTrace()}
827 * and related methods.
828 *
829 * This method, which is designed for use by RPC frameworks and other
830 * advanced systems, allows the client to override the default
831 * stack trace that is either generated by {@link #fillInStackTrace()}
832 * when a throwable is constructed or deserialized when a throwable is
833 * read from a serialization stream.
834 *
835 * <p>If the stack trace of this {@code Throwable} {@linkplain
836 * Throwable#Throwable(String, Throwable, boolean, boolean) is not
837 * writable}, calling this method has no effect other than
838 * validating its argument.
839 *
840 * @param stackTrace the stack trace elements to be associated with
841 * this {@code Throwable}. The specified array is copied by this
842 * call; changes in the specified array after the method invocation
843 * returns will have no affect on this {@code Throwable}'s stack
844 * trace.
845 *
846 * @throws NullPointerException if {@code stackTrace} is
847 * {@code null} or if any of the elements of
848 * {@code stackTrace} are {@code null}
849 *
850 * @since 1.4
851 */
852 public void setStackTrace(StackTraceElement[] stackTrace) {
853 Objects.requireNonNull(stackTrace);
854
855 if (this.stackTrace == null) // Immutable stack
856 return;
857
858 StackTraceElement[] defensiveCopy = stackTrace.clone();
859 for (int i = 0; i < defensiveCopy.length; i++) {
860 if (defensiveCopy[i] == null)
861 throw new NullPointerException("stackTrace[" + i + "]");
862 }
863
864 synchronized (this) {
865 this.stackTrace = defensiveCopy;
866 }
867 }
868
869 /**
870 * Returns the number of elements in the stack trace (or 0 if the stack
871 * trace is unavailable).
872 *
873 * package-protection for use by SharedSecrets.
874 */
875 native int getStackTraceDepth();
876
877 /**
878 * Returns the specified element of the stack trace.
879 *
880 * package-protection for use by SharedSecrets.
881 *
882 * @param index index of the element to return.
883 * @throws IndexOutOfBoundsException if {@code index < 0 ||
884 * index >= getStackTraceDepth() }
885 */
886 native StackTraceElement getStackTraceElement(int index);
887
888 /**
889 * Reads a {@code Throwable} from a stream, enforcing
890 * well-formedness constraints on fields. Null entries and
891 * self-pointers are not allowed in the list of {@code
892 * suppressedExceptions}. Null entries are not allowed for stack
893 * trace elements. A single-element stack trace whose entry is
894 * equal to {@code new StackTraceElement("", "", null,
895 * Integer.MIN_VALUE)} results in a {@code null} {@code
896 * stackTrace} field.
897 *
898 * Note that there are no constraints on the value the {@code
899 * cause} field can hold; both {@code null} and {@code this} are
900 * valid values for the field.
901 */
902 private void readObject(ObjectInputStream s)
903 throws IOException, ClassNotFoundException {
904 s.defaultReadObject(); // read in all fields
905 if (suppressedExceptions != null) {
906 List<Throwable> suppressed = null;
907 if (suppressedExceptions.isEmpty()) {
908 // Use the sentinel for a zero-length list
909 suppressed = SUPPRESSED_SENTINEL;
910 } else { // Copy Throwables to new list
911 suppressed = new ArrayList<>(1);
912 for (Throwable t : suppressedExceptions) {
913 // Enforce constraints on suppressed exceptions in
914 // case of corrupt or malicious stream.
915 if (t == null)
916 throw new NullPointerException(NULL_CAUSE_MESSAGE);
917 if (t == this)
918 throw new IllegalArgumentException(SELF_SUPPRESSION_MESSAGE);
919 suppressed.add(t);
920 }
921 }
922 suppressedExceptions = suppressed;
923 } // else a null suppressedExceptions field remains null
924
925 // Check for the marker of an immutable stack trace
926 if (stackTrace != null) {
927 // Share zero-length stack traces
928 if (stackTrace.length == 0) {
929 stackTrace = EMPTY_STACK;
930 } else if (stackTrace.length == 1 &&
931 SentinelHolder.STACK_TRACE_ELEMENT_SENTINEL.equals(stackTrace[0])) {
932 stackTrace = null;
933 } else { // Verify stack trace elements are non-null.
934 for(StackTraceElement ste : stackTrace) {
935 if (ste == null)
936 throw new NullPointerException("null StackTraceElement in serial stream. ");
937 }
938 }
939 }
940 // A null stackTrace field in the serial form can result from
941 // an exception serialized without that field. Such exceptions
942 // are now treated as having immutable stack traces.
943 }
944
945 /**
946 * Write a {@code Throwable} object to a stream.
947 *
948 * A {@code null} stack trace field is represented in the serial
949 * form as a one-element array whose element is equal to {@code
950 * new StackTraceElement("", "", null, Integer.MIN_VALUE)}.
951 */
952 private synchronized void writeObject(ObjectOutputStream s)
953 throws IOException {
954 // Ensure that the stackTrace field is initialized to a
955 // non-null value, if appropriate. As of JDK 7, a null stack
956 // trace field is a valid value indicating the stack trace
957 // should not be set.
958 getOurStackTrace();
959 ObjectOutputStream.PutField fields = s.putFields();
960
961 fields.put("detailMessage", detailMessage);
962 fields.put("cause", cause);
963 // Serialize a null stacktrace using the stack trace sentinel.
964 if (stackTrace == null)
965 fields.put("stackTrace", SentinelHolder.STACK_TRACE_SENTINEL);
966 else
967 fields.put("stackTrace", stackTrace);
968 fields.put("suppressedExceptions", suppressedExceptions);
969
970 s.writeFields();
971 }
972
973 /**
974 * Appends the specified exception to the exceptions that were
975 * suppressed in order to deliver this exception. This method is
976 * typically called (automatically and implicitly) by the {@code
977 * try}-with-resources statement.
978 *
979 * <p>The suppression behavior is enabled <em>unless</em> disabled
980 * {@linkplain #Throwable(String, Throwable, boolean) via a
981 * constructor}. When suppression is disabled, this method does
982 * nothing other than to validate its argument.
983 *
984 * <p>Note that when one exception {@linkplain
985 * #initCause(Throwable) causes} another exception, the first
986 * exception is usually caught and then the second exception is
987 * thrown in response. In other words, there is a causal
988 * connection between the two exceptions.
989 *
990 * In contrast, there are situations where two independent
1027 if (exception == null)
1028 throw new NullPointerException(NULL_CAUSE_MESSAGE);
1029
1030 if (suppressedExceptions == null) // Suppressed exceptions not recorded
1031 return;
1032
1033 if (suppressedExceptions == SUPPRESSED_SENTINEL)
1034 suppressedExceptions = new ArrayList<>(1);
1035
1036 suppressedExceptions.add(exception);
1037 }
1038
1039 private static final Throwable[] EMPTY_THROWABLE_ARRAY = new Throwable[0];
1040
1041 /**
1042 * Returns an array containing all of the exceptions that were
1043 * suppressed, typically by the {@code try}-with-resources
1044 * statement, in order to deliver this exception.
1045 *
1046 * If no exceptions were suppressed or {@linkplain
1047 * #Throwable(String, Throwable, boolean) suppression is disabled},
1048 * an empty array is returned.
1049 *
1050 * @return an array containing all of the exceptions that were
1051 * suppressed to deliver this exception.
1052 * @since 1.7
1053 */
1054 public final synchronized Throwable[] getSuppressed() {
1055 if (suppressedExceptions == SUPPRESSED_SENTINEL ||
1056 suppressedExceptions == null)
1057 return EMPTY_THROWABLE_ARRAY;
1058 else
1059 return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY);
1060 }
1061 }
|