1 /*
2 * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
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
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 }
|
1 *
2 * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
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
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 that the logical stack trace has been
158 * populated into the backtrace field.
159 */
160 private static final StackTraceElement[] FILLED_IN_STACK =
161 new StackTraceElement[] {new StackTraceElement("FILLED_IN", "STACK", null, -1)};
162
163 /**
164 * A shared value for an empty stack.
165 */
166 private static final StackTraceElement[] EMPTY_STACK = new StackTraceElement[0];
167
168 /*
169 * To allow Throwable objects to be made immutable and safely
170 * reused by the JVM, such as OutOfMemoryErrors, fields of
171 * Throwable that are writable in response to user actions, cause,
172 * stackTrace, and suppressedExceptions obey the following
173 * protocol:
174 *
175 * 1) The fields are initialized to a non-null sentinel value
176 * which indicates the value has logically not been set.
177 *
178 * 2) Writing a null to the field indicates further writes
179 * are forbidden
180 *
181 * 3) The sentinel value may be replaced with another non-null
182 * value.
183 *
184 * For example, implementations of the HotSpot JVM have
185 * preallocated OutOfMemoryError objects to provide for better
186 * diagnosability of that situation. These objects are created
187 * without calling the constructor for that class and the fields
188 * in question are initialized to null. To support this
189 * capability, any new fields added to Throwable that require
190 * being initialized to a non-null value require a coordinated JVM
191 * change.
192 */
193
194 /**
195 * The throwable that caused this throwable to get thrown, or null if this
196 * throwable was not caused by another throwable, or if the causative
197 * throwable is unknown. If this field is equal to this throwable itself,
198 * it indicates that the cause of this throwable has not yet been
199 * initialized.
200 *
201 * @serial
202 * @since 1.4
203 */
204 private Throwable cause = this;
205
206 /**
207 * The stack trace, as returned by {@link #getStackTrace()}.
208 *
209 * The field is initialized to a zero-length array. A {@code
210 * null} value of this field indicates subsequent calls to {@link
211 * #setStackTrace()} and {@link #fillInStackTrace} will be be no-ops.
212 *
213 * @serial
214 * @since 1.4
215 */
216 private StackTraceElement[] stackTrace = EMPTY_STACK;
217
218 // Setting this static field introduces an acceptable
219 // initialization dependency on a few java.util classes.
220 private static final List<Throwable> SUPPRESSED_SENTINEL =
221 Collections.unmodifiableList(new ArrayList<Throwable>(0));
222
223 /**
224 * The list of suppressed exceptions, as returned by {@link
225 * #getSuppressed()}. The list is initialized to a zero-element
226 * unmodifiable sentinel list. When a serialized Throwable is
227 * read in, if the {@code suppressedExceptions} field points to a
228 * zero-element list, the field is reset to the sentinel value.
229 *
230 * @serial
231 * @since 1.7
232 */
233 private List<Throwable> suppressedExceptions = SUPPRESSED_SENTINEL;
234
235 /** Message for trying to suppress a null exception. */
236 private static final String NULL_CAUSE_MESSAGE = "Cannot suppress a null exception.";
303 * wrappers for other throwables (for example, {@link
304 * java.security.PrivilegedActionException}).
305 *
306 * <p>The {@link #fillInStackTrace()} method is called to initialize
307 * the stack trace data in the newly created throwable.
308 *
309 * @param cause the cause (which is saved for later retrieval by the
310 * {@link #getCause()} method). (A {@code null} value is
311 * permitted, and indicates that the cause is nonexistent or
312 * unknown.)
313 * @since 1.4
314 */
315 public Throwable(Throwable cause) {
316 fillInStackTrace();
317 detailMessage = (cause==null ? null : cause.toString());
318 this.cause = cause;
319 }
320
321 /**
322 * Constructs a new throwable with the specified detail message,
323 * cause, {@linkplain #addSuppressed suppression} enabled or
324 * disabled, and writable stack trace enabled or disabled. If
325 * suppression is disabled, {@link #getSuppressed} for this object
326 * will return a zero-length array and calls to {@link
327 * #addSuppressed} that would otherwise append an exception to the
328 * suppressed list will have no effect. If the writable stack
329 * trace is false, this constructor will not call {@link
330 * #fillInStackTrace()} and subsequent calls to {@code
331 * fillInStackTrace} and {@link
332 * #setStackTrace(StackTraceElement[])} will not set the stack
333 * trace. If the writable stack trace is false, {@link
334 * #getStackTrace} will return a zero length array.
335 *
336 * <p>Note that the other constructors of {@code Throwable} treat
337 * suppression as being enabled and the stack trace as being
338 * writable. Subclasses of {@code Throwable} should document any
339 * conditions under which suppression is disabled. Disabling of
340 * suppression should only occur in exceptional circumstances
341 * where special requirements exist, such as a virtual machine
342 * reusing exception objects under low-memory situations.
343 *
344 * @param message the detail message.
345 * @param cause the cause. (A {@code null} value is permitted,
346 * and indicates that the cause is nonexistent or unknown.)
347 * @param enableSuppression whether or not suppression is enabled or disabled
348 * @param writableStackTrace whether or not the stack trace should be
349 * writable
350 *
351 * @see OutOfMemoryError
352 * @see NullPointerException
353 * @see ArithmeticException
354 * @since 1.7
355 */
356 protected Throwable(String message, Throwable cause,
357 boolean enableSuppression,
358 boolean writableStackTrace) {
359 if (writableStackTrace) {
360 fillInStackTrace();
361 } else {
362 stackTrace = null;
363 }
364 detailMessage = message;
365 this.cause = cause;
366 if (!enableSuppression)
367 suppressedExceptions = null;
368 }
369
370 /**
371 * Returns the detail message string of this throwable.
372 *
373 * @return the detail message string of this {@code Throwable} instance
374 * (which may be {@code null}).
375 */
376 public String getMessage() {
377 return detailMessage;
378 }
379
380 /**
381 * Creates a localized description of this throwable.
382 * Subclasses may override this method in order to produce a
383 * locale-specific message. For subclasses that do not override this
740 private final PrintWriter printWriter;
741
742 WrappedPrintWriter(PrintWriter printWriter) {
743 this.printWriter = printWriter;
744 }
745
746 Object lock() {
747 return printWriter;
748 }
749
750 void println(Object o) {
751 printWriter.println(o);
752 }
753 }
754
755 /**
756 * Fills in the execution stack trace. This method records within this
757 * {@code Throwable} object information about the current state of
758 * the stack frames for the current thread.
759 *
760 * <p>If the stack trace of this {@code Throwable} {@linkplain
761 * Throwable#Throwable(String, Throwable, boolean, boolean) is not
762 * writable}, calling this method has no effect.
763 *
764 * @return a reference to this {@code Throwable} instance.
765 * @see java.lang.Throwable#printStackTrace()
766 */
767 public synchronized Throwable fillInStackTrace() {
768 if (stackTrace != null) {
769 fillInStackTrace(0);
770 stackTrace = FILLED_IN_STACK;
771 }
772 return this;
773 }
774
775 private native Throwable fillInStackTrace(int dummy);
776
777 /**
778 * Provides programmatic access to the stack trace information printed by
779 * {@link #printStackTrace()}. Returns an array of stack trace elements,
780 * each representing one stack frame. The zeroth element of the array
781 * (assuming the array's length is non-zero) represents the top of the
782 * stack, which is the last method invocation in the sequence. Typically,
783 * this is the point at which this throwable was created and thrown.
784 * The last element of the array (assuming the array's length is non-zero)
785 * represents the bottom of the stack, which is the first method invocation
786 * in the sequence.
787 *
788 * <p>Some virtual machines may, under some circumstances, omit one
789 * or more stack frames from the stack trace. In the extreme case,
790 * a virtual machine that has no stack trace information concerning
791 * this throwable is permitted to return a zero-length array from this
792 * method. Generally speaking, the array returned by this method will
793 * contain one element for every frame that would be printed by
794 * {@code printStackTrace}.
795 *
796 * @return an array of stack trace elements representing the stack trace
797 * pertaining to this throwable.
798 * @since 1.4
799 */
800 public StackTraceElement[] getStackTrace() {
801 return getOurStackTrace().clone();
802 }
803
804 private synchronized StackTraceElement[] getOurStackTrace() {
805 // Initialize stack trace field with information from
806 // backtrace if this is the first call to this method
807 if (stackTrace == FILLED_IN_STACK) {
808 int depth = getStackTraceDepth();
809 stackTrace = new StackTraceElement[depth];
810 for (int i=0; i < depth; i++)
811 stackTrace[i] = getStackTraceElement(i);
812 } else if (stackTrace == null) {
813 return EMPTY_STACK;
814 }
815 return stackTrace;
816 }
817
818 /**
819 * Sets the stack trace elements that will be returned by
820 * {@link #getStackTrace()} and printed by {@link #printStackTrace()}
821 * and related methods.
822 *
823 * This method, which is designed for use by RPC frameworks and other
824 * advanced systems, allows the client to override the default
825 * stack trace that is either generated by {@link #fillInStackTrace()}
826 * when a throwable is constructed or deserialized when a throwable is
827 * read from a serialization stream.
828 *
829 * <p>If the stack trace of this {@code Throwable} {@linkplain
830 * Throwable#Throwable(String, Throwable, boolean, boolean) is not
831 * writable}, calling this method has no effect other than
832 * validating its argument.
833 *
834 * @param stackTrace the stack trace elements to be associated with
835 * this {@code Throwable}. The specified array is copied by this
836 * call; changes in the specified array after the method invocation
837 * returns will have no affect on this {@code Throwable}'s stack
838 * trace.
839 *
840 * @throws NullPointerException if {@code stackTrace} is
841 * {@code null} or if any of the elements of
842 * {@code stackTrace} are {@code null}
843 *
844 * @since 1.4
845 */
846 public void setStackTrace(StackTraceElement[] stackTrace) {
847 // Validate argument
848 StackTraceElement[] defensiveCopy = stackTrace.clone();
849 for (int i = 0; i < defensiveCopy.length; i++) {
850 if (defensiveCopy[i] == null)
851 throw new NullPointerException("stackTrace[" + i + "]");
852 }
853
854 if (this.stackTrace == null) // Immutable stack
855 return;
856
857 synchronized (this) {
858 this.stackTrace = defensiveCopy;
859 }
860 }
861
862 /**
863 * Returns the number of elements in the stack trace (or 0 if the stack
864 * trace is unavailable).
865 *
866 * package-protection for use by SharedSecrets.
867 */
868 native int getStackTraceDepth();
869
870 /**
871 * Returns the specified element of the stack trace.
872 *
873 * package-protection for use by SharedSecrets.
874 *
875 * @param index index of the element to return.
876 * @throws IndexOutOfBoundsException if {@code index < 0 ||
877 * index >= getStackTraceDepth() }
878 */
879 native StackTraceElement getStackTraceElement(int index);
880
881 /**
882 * Reads a {@code Throwable} from a stream, enforcing
883 * well-formedness constraints on fields. Null entries and
884 * self-pointers are not allowed in the list of {@code
885 * suppressedExceptions}. Null entries are not allowed for stack
886 * trace elements. A single-element stack trace whose entry is
887 * equal to {@code new StackTraceElement("", "", null,
888 * Integer.MIN_VALUE)} results in a {@code null} {@code
889 * stackTrace} field.
890 *
891 * Note that there are no constraints on the value the {@code
892 * cause} field can hold; both {@code null} and {@code this} are
893 * valid values for the field.
894 */
895 private void readObject(ObjectInputStream s)
896 throws IOException, ClassNotFoundException {
897 s.defaultReadObject(); // read in all fields
898 if (suppressedExceptions != null) {
899 List<Throwable> suppressed = null;
900 if (suppressedExceptions.isEmpty()) {
901 // Use the sentinel for a zero-length list
902 suppressed = SUPPRESSED_SENTINEL;
903 } else { // Copy Throwables to new list
904 suppressed = new ArrayList<>(1);
905 for (Throwable t : suppressedExceptions) {
906 // Enforce constraints on suppressed exceptions in
907 // case of corrupt or malicious stream.
908 if (t == null)
909 throw new NullPointerException(NULL_CAUSE_MESSAGE);
910 if (t == this)
911 throw new IllegalArgumentException(SELF_SUPPRESSION_MESSAGE);
912 suppressed.add(t);
913 }
914 }
915 suppressedExceptions = suppressed;
916 } // else a null suppressedExceptions field remains null
917
918 // Check for the marker of an immutable stack trace
919 if (stackTrace != null) {
920 // Share zero-length stack traces
921 if (stackTrace.length == 0) {
922 stackTrace = EMPTY_STACK;
923 } else if (stackTrace.length == 1 &&
924 SentinelHolder.STACK_TRACE_ELEMENT_SENTINEL.equals(stackTrace[0])) {
925 stackTrace = null;
926 } else { // Verify stack trace elements are non-null.
927 for(StackTraceElement ste : stackTrace) {
928 if (ste == null)
929 throw new NullPointerException("null StackTraceElement in serial stream. ");
930 }
931 }
932 } else {
933 // A null stackTrace field in the serial form can result
934 // from an exception serialized without that field in
935 // older JDK releases; treat such exceptions as having
936 // empty stack traces.
937 stackTrace = EMPTY_STACK;
938 }
939 }
940
941 /**
942 * Write a {@code Throwable} object to a stream.
943 *
944 * A {@code null} stack trace field is represented in the serial
945 * form as a one-element array whose element is equal to {@code
946 * new StackTraceElement("", "", null, Integer.MIN_VALUE)}.
947 */
948 private synchronized void writeObject(ObjectOutputStream s)
949 throws IOException {
950 // Ensure that the stackTrace field is initialized to a
951 // non-null value, if appropriate. As of JDK 7, a null stack
952 // trace field is a valid value indicating the stack trace
953 // should not be set.
954 getOurStackTrace();
955 ObjectOutputStream.PutField fields = s.putFields();
956
957 fields.put("detailMessage", detailMessage);
958 fields.put("cause", cause);
959 // Serialize a null stacktrace using the stack trace sentinel.
960 if (stackTrace == null)
961 fields.put("stackTrace", SentinelHolder.STACK_TRACE_SENTINEL);
962 else
963 fields.put("stackTrace", stackTrace);
964 fields.put("suppressedExceptions", suppressedExceptions);
965
966 s.writeFields();
967 }
968
969 /**
970 * Appends the specified exception to the exceptions that were
971 * suppressed in order to deliver this exception. This method is
972 * typically called (automatically and implicitly) by the {@code
973 * try}-with-resources statement.
974 *
975 * <p>The suppression behavior is enabled <em>unless</em> disabled
976 * {@linkplain #Throwable(String, Throwable, boolean) via a
977 * constructor}. When suppression is disabled, this method does
978 * nothing other than to validate its argument.
979 *
980 * <p>Note that when one exception {@linkplain
981 * #initCause(Throwable) causes} another exception, the first
982 * exception is usually caught and then the second exception is
983 * thrown in response. In other words, there is a causal
984 * connection between the two exceptions.
985 *
986 * In contrast, there are situations where two independent
1023 if (exception == null)
1024 throw new NullPointerException(NULL_CAUSE_MESSAGE);
1025
1026 if (suppressedExceptions == null) // Suppressed exceptions not recorded
1027 return;
1028
1029 if (suppressedExceptions == SUPPRESSED_SENTINEL)
1030 suppressedExceptions = new ArrayList<>(1);
1031
1032 suppressedExceptions.add(exception);
1033 }
1034
1035 private static final Throwable[] EMPTY_THROWABLE_ARRAY = new Throwable[0];
1036
1037 /**
1038 * Returns an array containing all of the exceptions that were
1039 * suppressed, typically by the {@code try}-with-resources
1040 * statement, in order to deliver this exception.
1041 *
1042 * If no exceptions were suppressed or {@linkplain
1043 * #Throwable(String, Throwable, boolean) suppression is disabled},
1044 * an empty array is returned.
1045 *
1046 * @return an array containing all of the exceptions that were
1047 * suppressed to deliver this exception.
1048 * @since 1.7
1049 */
1050 public final synchronized Throwable[] getSuppressed() {
1051 if (suppressedExceptions == SUPPRESSED_SENTINEL ||
1052 suppressedExceptions == null)
1053 return EMPTY_THROWABLE_ARRAY;
1054 else
1055 return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY);
1056 }
1057 }
|