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