src/java.base/share/classes/java/lang/Throwable.java
changeset 55709 ce3598fceb87
parent 54059 1bc8513104f2
child 55717 2b4e14968afd
equal deleted inserted replaced
55708:2b0acaf92ecc 55709:ce3598fceb87
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 package java.lang;
    26 package java.lang;
    27 
    27 
    28 import  java.io.*;
    28 import java.io.*;
    29 import  java.util.*;
    29 import java.util.*;
    30 
    30 
    31 /**
    31 /**
    32  * The {@code Throwable} class is the superclass of all errors and
    32  * The {@code Throwable} class is the superclass of all errors and
    33  * exceptions in the Java language. Only objects that are instances of this
    33  * exceptions in the Java language. Only objects that are instances of this
    34  * class (or one of its subclasses) are thrown by the Java Virtual Machine or
    34  * class (or one of its subclasses) are thrown by the Java Virtual Machine or
   902      * valid values for the field.
   902      * valid values for the field.
   903      */
   903      */
   904     private void readObject(ObjectInputStream s)
   904     private void readObject(ObjectInputStream s)
   905         throws IOException, ClassNotFoundException {
   905         throws IOException, ClassNotFoundException {
   906         s.defaultReadObject();     // read in all fields
   906         s.defaultReadObject();     // read in all fields
   907         if (suppressedExceptions != null) {
   907 
   908             List<Throwable> suppressed = null;
   908         // Set suppressed exceptions and stack trace elements fields
   909             if (suppressedExceptions.isEmpty()) {
   909         // to marker values until the contents from the serial stream
   910                 // Use the sentinel for a zero-length list
   910         // are validated.
   911                 suppressed = SUPPRESSED_SENTINEL;
   911         List<Throwable> candidateSuppressedExceptions = suppressedExceptions;
   912             } else { // Copy Throwables to new list
   912         suppressedExceptions = SUPPRESSED_SENTINEL;
   913                 suppressed = new ArrayList<>(1);
   913 
   914                 for (Throwable t : suppressedExceptions) {
   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) {
   915                     // Enforce constraints on suppressed exceptions in
   923                     // Enforce constraints on suppressed exceptions in
   916                     // case of corrupt or malicious stream.
   924                     // case of corrupt or malicious stream.
   917                     Objects.requireNonNull(t, NULL_CAUSE_MESSAGE);
   925                     Objects.requireNonNull(t, NULL_CAUSE_MESSAGE);
   918                     if (t == this)
   926                     if (t == this)
   919                         throw new IllegalArgumentException(SELF_SUPPRESSION_MESSAGE);
   927                         throw new IllegalArgumentException(SELF_SUPPRESSION_MESSAGE);
   920                     suppressed.add(t);
   928                     suppList.add(t);
   921                 }
   929                 }
       
   930                 // If there are any invalid suppressed exceptions,
       
   931                 // implicitly use the sentinel value assigned earlier.
       
   932                 suppressedExceptions = suppList;
   922             }
   933             }
   923             suppressedExceptions = suppressed;
   934         } else {
   924         } // else a null suppressedExceptions field remains null
   935             suppressedExceptions = null;
       
   936         }
   925 
   937 
   926         /*
   938         /*
   927          * For zero-length stack traces, use a clone of
   939          * For zero-length stack traces, use a clone of
   928          * UNASSIGNED_STACK rather than UNASSIGNED_STACK itself to
   940          * UNASSIGNED_STACK rather than UNASSIGNED_STACK itself to
   929          * allow identity comparison against UNASSIGNED_STACK in
   941          * allow identity comparison against UNASSIGNED_STACK in
   930          * getOurStackTrace.  The identity of UNASSIGNED_STACK in
   942          * getOurStackTrace.  The identity of UNASSIGNED_STACK in
   931          * stackTrace indicates to the getOurStackTrace method that
   943          * stackTrace indicates to the getOurStackTrace method that
   932          * the stackTrace needs to be constructed from the information
   944          * the stackTrace needs to be constructed from the information
   933          * in backtrace.
   945          * in backtrace.
   934          */
   946          */
   935         if (stackTrace != null) {
   947         if (candidateStackTrace != null) {
   936             if (stackTrace.length == 0) {
   948             // Work from a clone of the candidateStackTrace to ensure
   937                 stackTrace = UNASSIGNED_STACK.clone();
   949             // consistency of checks.
   938             }  else if (stackTrace.length == 1 &&
   950             candidateStackTrace = candidateStackTrace.clone();
       
   951             if (candidateStackTrace.length >= 1) {
       
   952                 if (candidateStackTrace.length == 1 &&
   939                         // Check for the marker of an immutable stack trace
   953                         // Check for the marker of an immutable stack trace
   940                         SentinelHolder.STACK_TRACE_ELEMENT_SENTINEL.equals(stackTrace[0])) {
   954                         SentinelHolder.STACK_TRACE_ELEMENT_SENTINEL.equals(candidateStackTrace[0])) {
   941                 stackTrace = null;
   955                     stackTrace = null;
   942             } else { // Verify stack trace elements are non-null.
   956                 } else { // Verify stack trace elements are non-null.
   943                 for(StackTraceElement ste : stackTrace) {
   957                     for (StackTraceElement ste : candidateStackTrace) {
   944                     Objects.requireNonNull(ste, "null StackTraceElement in serial stream.");
   958                         Objects.requireNonNull(ste, "null StackTraceElement in serial stream.");
       
   959                     }
       
   960                     stackTrace = candidateStackTrace;
   945                 }
   961                 }
   946             }
   962             }
       
   963         }
       
   964         // A null stackTrace field in the serial form can result from
       
   965         // an exception serialized without that field in older JDK
       
   966         // releases; treat such exceptions as having empty stack
       
   967         // traces by leaving stackTrace assigned to a clone of
       
   968         // UNASSIGNED_STACK.
       
   969     }
       
   970 
       
   971     private int validateSuppressedExceptionsList(List<Throwable> deserSuppressedExceptions)
       
   972         throws IOException {
       
   973         if (!Object.class.getModule().
       
   974             equals(deserSuppressedExceptions.getClass().getModule())) {
       
   975             throw new StreamCorruptedException("List implementation not in base module.");
   947         } else {
   976         } else {
   948             // A null stackTrace field in the serial form can result
   977             int size = deserSuppressedExceptions.size();
   949             // from an exception serialized without that field in
   978             if (size < 0) {
   950             // older JDK releases; treat such exceptions as having
   979                 throw new StreamCorruptedException("Negative list size reported.");
   951             // empty stack traces.
   980             }
   952             stackTrace = UNASSIGNED_STACK.clone();
   981             return size;
   953         }
   982         }
   954     }
   983     }
   955 
   984 
   956     /**
   985     /**
   957      * Write a {@code Throwable} object to a stream.
   986      * Write a {@code Throwable} object to a stream.