jdk/src/share/classes/java/lang/Throwable.java
changeset 6302 ec168532bf3f
parent 6110 6db4b0180328
child 6515 7a5ccc90b436
equal deleted inserted replaced
6300:700ec2a5d680 6302:ec168532bf3f
   198      * {@link #getSuppressedExceptions()}.
   198      * {@link #getSuppressedExceptions()}.
   199      *
   199      *
   200      * @serial
   200      * @serial
   201      * @since 1.7
   201      * @since 1.7
   202      */
   202      */
   203     private List<Throwable> suppressedExceptions = Collections.emptyList();
   203     private List<Throwable> suppressedExceptions = null;
       
   204     /*
       
   205      * This field is lazily initialized when the first suppressed
       
   206      * exception is added.
       
   207      *
       
   208      * OutOfMemoryError is preallocated in the VM for better OOM
       
   209      * diagnosability during VM initialization. Constructor can't
       
   210      * be not invoked. If a new field to be added in the future must
       
   211      * be initialized to non-null, it requires a synchronized VM change.
       
   212      */
   204 
   213 
   205     /** Message for trying to suppress a null exception. */
   214     /** Message for trying to suppress a null exception. */
   206     private static final String NULL_CAUSE_MESSAGE = "Cannot suppress a null exception.";
   215     private static final String NULL_CAUSE_MESSAGE = "Cannot suppress a null exception.";
   207 
   216 
   208     /** Caption  for labeling causative exception stack traces */
   217     /** Caption  for labeling causative exception stack traces */
   327      *
   336      *
   328      * @return  the cause of this throwable or {@code null} if the
   337      * @return  the cause of this throwable or {@code null} if the
   329      *          cause is nonexistent or unknown.
   338      *          cause is nonexistent or unknown.
   330      * @since 1.4
   339      * @since 1.4
   331      */
   340      */
   332     public Throwable getCause() {
   341     public synchronized Throwable getCause() {
   333         return (cause==this ? null : cause);
   342         return (cause==this ? null : cause);
   334     }
   343     }
   335 
   344 
   336     /**
   345     /**
   337      * Initializes the <i>cause</i> of this throwable to the specified value.
   346      * Initializes the <i>cause</i> of this throwable to the specified value.
   561             StackTraceElement[] trace = getOurStackTrace();
   570             StackTraceElement[] trace = getOurStackTrace();
   562             for (StackTraceElement traceElement : trace)
   571             for (StackTraceElement traceElement : trace)
   563                 s.println("\tat " + traceElement);
   572                 s.println("\tat " + traceElement);
   564 
   573 
   565             // Print suppressed exceptions, if any
   574             // Print suppressed exceptions, if any
   566             for (Throwable se : suppressedExceptions)
   575             for (Throwable se : getSuppressedExceptions())
   567                 se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu);
   576                 se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu);
   568 
   577 
   569             // Print cause, if any
   578             // Print cause, if any
   570             Throwable ourCause = getCause();
   579             Throwable ourCause = getCause();
   571             if (ourCause != null)
   580             if (ourCause != null)
   602                 s.println(prefix + "\tat " + trace[i]);
   611                 s.println(prefix + "\tat " + trace[i]);
   603             if (framesInCommon != 0)
   612             if (framesInCommon != 0)
   604                 s.println(prefix + "\t... " + framesInCommon + " more");
   613                 s.println(prefix + "\t... " + framesInCommon + " more");
   605 
   614 
   606             // Print suppressed exceptions, if any
   615             // Print suppressed exceptions, if any
   607             for (Throwable se : suppressedExceptions)
   616             for (Throwable se : getSuppressedExceptions())
   608                 se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION,
   617                 se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION,
   609                                            prefix +"\t", dejaVu);
   618                                            prefix +"\t", dejaVu);
   610 
   619 
   611             // Print cause, if any
   620             // Print cause, if any
   612             Throwable ourCause = getCause();
   621             Throwable ourCause = getCause();
   745         StackTraceElement[] defensiveCopy = stackTrace.clone();
   754         StackTraceElement[] defensiveCopy = stackTrace.clone();
   746         for (int i = 0; i < defensiveCopy.length; i++)
   755         for (int i = 0; i < defensiveCopy.length; i++)
   747             if (defensiveCopy[i] == null)
   756             if (defensiveCopy[i] == null)
   748                 throw new NullPointerException("stackTrace[" + i + "]");
   757                 throw new NullPointerException("stackTrace[" + i + "]");
   749 
   758 
   750         this.stackTrace = defensiveCopy;
   759         synchronized (this) {
       
   760             this.stackTrace = defensiveCopy;
       
   761         }
   751     }
   762     }
   752 
   763 
   753     /**
   764     /**
   754      * Returns the number of elements in the stack trace (or 0 if the stack
   765      * Returns the number of elements in the stack trace (or 0 if the stack
   755      * trace is unavailable).
   766      * trace is unavailable).
   770     native StackTraceElement getStackTraceElement(int index);
   781     native StackTraceElement getStackTraceElement(int index);
   771 
   782 
   772     private void readObject(ObjectInputStream s)
   783     private void readObject(ObjectInputStream s)
   773         throws IOException, ClassNotFoundException {
   784         throws IOException, ClassNotFoundException {
   774         s.defaultReadObject();     // read in all fields
   785         s.defaultReadObject();     // read in all fields
   775         List<Throwable> suppressed = Collections.emptyList();
   786         List<Throwable> suppressed = null;
   776         if (suppressedExceptions != null &&
   787         if (suppressedExceptions != null &&
   777             !suppressedExceptions.isEmpty()) { // Copy Throwables to new list
   788             !suppressedExceptions.isEmpty()) { // Copy Throwables to new list
   778             suppressed = new ArrayList<Throwable>();
   789             suppressed = new ArrayList<Throwable>();
   779             for(Throwable t : suppressedExceptions) {
   790             for (Throwable t : suppressedExceptions) {
   780                 if (t == null)
   791                 if (t == null)
   781                     throw new NullPointerException(NULL_CAUSE_MESSAGE);
   792                     throw new NullPointerException(NULL_CAUSE_MESSAGE);
   782                 suppressed.add(t);
   793                 suppressed.add(t);
   783             }
   794             }
   784         }
   795         }
   817         if (exception == null)
   828         if (exception == null)
   818             throw new NullPointerException(NULL_CAUSE_MESSAGE);
   829             throw new NullPointerException(NULL_CAUSE_MESSAGE);
   819         if (exception == this)
   830         if (exception == this)
   820             throw new IllegalArgumentException("Self-suppression not permitted");
   831             throw new IllegalArgumentException("Self-suppression not permitted");
   821 
   832 
   822         if (suppressedExceptions.size() == 0)
   833         if (suppressedExceptions == null)
   823             suppressedExceptions = new ArrayList<Throwable>();
   834             suppressedExceptions = new ArrayList<Throwable>();
   824         suppressedExceptions.add(exception);
   835         suppressedExceptions.add(exception);
   825     }
   836     }
   826 
   837 
   827     private static final Throwable[] EMPTY_THROWABLE_ARRAY = new Throwable[0];
   838     private static final Throwable[] EMPTY_THROWABLE_ARRAY = new Throwable[0];
   833      *
   844      *
   834      * @return an array containing all of the exceptions that were
   845      * @return an array containing all of the exceptions that were
   835      *         suppressed to deliver this exception.
   846      *         suppressed to deliver this exception.
   836      * @since 1.7
   847      * @since 1.7
   837      */
   848      */
   838     public Throwable[] getSuppressedExceptions() {
   849     public synchronized Throwable[] getSuppressedExceptions() {
   839         return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY);
   850         if (suppressedExceptions == null)
       
   851             return EMPTY_THROWABLE_ARRAY;
       
   852         else
       
   853             return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY);
   840     }
   854     }
   841 }
   855 }