97 * implementation predates the addition of the exception chaining mechanism to
98 * {@code Throwable}.
99 *
100 * <p>By convention, class {@code Throwable} and its subclasses have two
101 * constructors, one that takes no arguments and one that takes a
102 * {@code String} argument that can be used to produce a detail message.
103 * Further, those subclasses that might likely have a cause associated with
104 * them should have two more constructors, one that takes a
105 * {@code Throwable} (the cause), and one that takes a
106 * {@code String} (the detail message) and a {@code Throwable} (the
107 * cause).
108 *
109 * @author unascribed
110 * @author Josh Bloch (Added exception chaining and programmatic access to
111 * stack trace in 1.4.)
112 * @jls 11.2 Compile-Time Checking of Exceptions
113 * @since 1.0
114 */
115 public class Throwable implements Serializable {
116 /** use serialVersionUID from JDK 1.0.2 for interoperability */
117 private static final long serialVersionUID = -3042686055658047285L;
118
119 /**
120 * The JVM saves some indication of the stack backtrace in this slot.
121 */
122 private transient Object backtrace;
123
124 /**
125 * Specific details about the Throwable. For example, for
126 * {@code FileNotFoundException}, this contains the name of
127 * the file that could not be found.
128 *
129 * @serial
130 */
131 private String detailMessage;
132
133
134 /**
135 * Holder class to defer initializing sentinel objects only used
136 * for serialization.
884 return;
885 this.stackTrace = defensiveCopy;
886 }
887 }
888
889 /**
890 * Reads a {@code Throwable} from a stream, enforcing
891 * well-formedness constraints on fields. Null entries and
892 * self-pointers are not allowed in the list of {@code
893 * suppressedExceptions}. Null entries are not allowed for stack
894 * trace elements. A null stack trace in the serial form results
895 * in a zero-length stack element array. A single-element stack
896 * trace whose entry is equal to {@code new StackTraceElement("",
897 * "", null, Integer.MIN_VALUE)} results in a {@code null} {@code
898 * stackTrace} field.
899 *
900 * Note that there are no constraints on the value the {@code
901 * cause} field can hold; both {@code null} and {@code this} are
902 * valid values for the field.
903 */
904 private void readObject(ObjectInputStream s)
905 throws IOException, ClassNotFoundException {
906 s.defaultReadObject(); // read in all fields
907
908 // Set suppressed exceptions and stack trace elements fields
909 // to marker values until the contents from the serial stream
910 // are validated.
911 List<Throwable> candidateSuppressedExceptions = suppressedExceptions;
912 suppressedExceptions = SUPPRESSED_SENTINEL;
913
914 StackTraceElement[] candidateStackTrace = stackTrace;
915 stackTrace = UNASSIGNED_STACK.clone();
916
917 if (candidateSuppressedExceptions != null) {
918 int suppressedSize = validateSuppressedExceptionsList(candidateSuppressedExceptions);
919 if (suppressedSize > 0) { // Copy valid Throwables to new list
920 var suppList = new ArrayList<Throwable>(Math.min(100, suppressedSize));
921
922 for (Throwable t : candidateSuppressedExceptions) {
923 // Enforce constraints on suppressed exceptions in
972 throws IOException {
973 if (!Object.class.getModule().
974 equals(deserSuppressedExceptions.getClass().getModule())) {
975 throw new StreamCorruptedException("List implementation not in base module.");
976 } else {
977 int size = deserSuppressedExceptions.size();
978 if (size < 0) {
979 throw new StreamCorruptedException("Negative list size reported.");
980 }
981 return size;
982 }
983 }
984
985 /**
986 * Write a {@code Throwable} object to a stream.
987 *
988 * A {@code null} stack trace field is represented in the serial
989 * form as a one-element array whose element is equal to {@code
990 * new StackTraceElement("", "", null, Integer.MIN_VALUE)}.
991 */
992 private synchronized void writeObject(ObjectOutputStream s)
993 throws IOException {
994 // Ensure that the stackTrace field is initialized to a
995 // non-null value, if appropriate. As of JDK 7, a null stack
996 // trace field is a valid value indicating the stack trace
997 // should not be set.
998 getOurStackTrace();
999
1000 StackTraceElement[] oldStackTrace = stackTrace;
1001 try {
1002 if (stackTrace == null)
1003 stackTrace = SentinelHolder.STACK_TRACE_SENTINEL;
1004 s.defaultWriteObject();
1005 } finally {
1006 stackTrace = oldStackTrace;
1007 }
1008 }
1009
1010 /**
1011 * Appends the specified exception to the exceptions that were
|
97 * implementation predates the addition of the exception chaining mechanism to
98 * {@code Throwable}.
99 *
100 * <p>By convention, class {@code Throwable} and its subclasses have two
101 * constructors, one that takes no arguments and one that takes a
102 * {@code String} argument that can be used to produce a detail message.
103 * Further, those subclasses that might likely have a cause associated with
104 * them should have two more constructors, one that takes a
105 * {@code Throwable} (the cause), and one that takes a
106 * {@code String} (the detail message) and a {@code Throwable} (the
107 * cause).
108 *
109 * @author unascribed
110 * @author Josh Bloch (Added exception chaining and programmatic access to
111 * stack trace in 1.4.)
112 * @jls 11.2 Compile-Time Checking of Exceptions
113 * @since 1.0
114 */
115 public class Throwable implements Serializable {
116 /** use serialVersionUID from JDK 1.0.2 for interoperability */
117 @java.io.Serial
118 private static final long serialVersionUID = -3042686055658047285L;
119
120 /**
121 * The JVM saves some indication of the stack backtrace in this slot.
122 */
123 private transient Object backtrace;
124
125 /**
126 * Specific details about the Throwable. For example, for
127 * {@code FileNotFoundException}, this contains the name of
128 * the file that could not be found.
129 *
130 * @serial
131 */
132 private String detailMessage;
133
134
135 /**
136 * Holder class to defer initializing sentinel objects only used
137 * for serialization.
885 return;
886 this.stackTrace = defensiveCopy;
887 }
888 }
889
890 /**
891 * Reads a {@code Throwable} from a stream, enforcing
892 * well-formedness constraints on fields. Null entries and
893 * self-pointers are not allowed in the list of {@code
894 * suppressedExceptions}. Null entries are not allowed for stack
895 * trace elements. A null stack trace in the serial form results
896 * in a zero-length stack element array. A single-element stack
897 * trace whose entry is equal to {@code new StackTraceElement("",
898 * "", null, Integer.MIN_VALUE)} results in a {@code null} {@code
899 * stackTrace} field.
900 *
901 * Note that there are no constraints on the value the {@code
902 * cause} field can hold; both {@code null} and {@code this} are
903 * valid values for the field.
904 */
905 @java.io.Serial
906 private void readObject(ObjectInputStream s)
907 throws IOException, ClassNotFoundException {
908 s.defaultReadObject(); // read in all fields
909
910 // Set suppressed exceptions and stack trace elements fields
911 // to marker values until the contents from the serial stream
912 // are validated.
913 List<Throwable> candidateSuppressedExceptions = suppressedExceptions;
914 suppressedExceptions = SUPPRESSED_SENTINEL;
915
916 StackTraceElement[] candidateStackTrace = stackTrace;
917 stackTrace = UNASSIGNED_STACK.clone();
918
919 if (candidateSuppressedExceptions != null) {
920 int suppressedSize = validateSuppressedExceptionsList(candidateSuppressedExceptions);
921 if (suppressedSize > 0) { // Copy valid Throwables to new list
922 var suppList = new ArrayList<Throwable>(Math.min(100, suppressedSize));
923
924 for (Throwable t : candidateSuppressedExceptions) {
925 // Enforce constraints on suppressed exceptions in
974 throws IOException {
975 if (!Object.class.getModule().
976 equals(deserSuppressedExceptions.getClass().getModule())) {
977 throw new StreamCorruptedException("List implementation not in base module.");
978 } else {
979 int size = deserSuppressedExceptions.size();
980 if (size < 0) {
981 throw new StreamCorruptedException("Negative list size reported.");
982 }
983 return size;
984 }
985 }
986
987 /**
988 * Write a {@code Throwable} object to a stream.
989 *
990 * A {@code null} stack trace field is represented in the serial
991 * form as a one-element array whose element is equal to {@code
992 * new StackTraceElement("", "", null, Integer.MIN_VALUE)}.
993 */
994 @java.io.Serial
995 private synchronized void writeObject(ObjectOutputStream s)
996 throws IOException {
997 // Ensure that the stackTrace field is initialized to a
998 // non-null value, if appropriate. As of JDK 7, a null stack
999 // trace field is a valid value indicating the stack trace
1000 // should not be set.
1001 getOurStackTrace();
1002
1003 StackTraceElement[] oldStackTrace = stackTrace;
1004 try {
1005 if (stackTrace == null)
1006 stackTrace = SentinelHolder.STACK_TRACE_SENTINEL;
1007 s.defaultWriteObject();
1008 } finally {
1009 stackTrace = oldStackTrace;
1010 }
1011 }
1012
1013 /**
1014 * Appends the specified exception to the exceptions that were
|