jdk/src/share/classes/java/lang/Throwable.java
changeset 7186 7f5fe8985263
parent 6515 7a5ccc90b436
child 7803 56bc97d69d93
equal deleted inserted replaced
7185:0ca9d322c703 7186:7f5fe8985263
     1 /*
     1 /*
     2  * Copyright (c) 1994, 2006, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
   168      * @serial
   168      * @serial
   169      */
   169      */
   170     private String detailMessage;
   170     private String detailMessage;
   171 
   171 
   172     /**
   172     /**
       
   173      * A shared value for an empty stack.
       
   174      */
       
   175     private static final StackTraceElement[] EMPTY_STACK = new StackTraceElement[0];
       
   176 
       
   177     /*
       
   178      * To allow Throwable objects to be made immutable and safely
       
   179      * reused by the JVM, such as OutOfMemoryErrors, fields of
       
   180      * Throwable that are writable in response to user actions, cause
       
   181      * and suppressedExceptions obey the following protocol:
       
   182      *
       
   183      * 1) The fields are initialized to a non-null sentinel value
       
   184      * which indicates the value has logically not been set.
       
   185      *
       
   186      * 2) Writing a null to the field indicates further writes
       
   187      * are forbidden
       
   188      *
       
   189      * 3) The sentinel value may be replaced with another non-null
       
   190      * value.
       
   191      *
       
   192      * For example, implementations of the HotSpot JVM have
       
   193      * preallocated OutOfMemoryError objects to provide for better
       
   194      * diagnosability of that situation.  These objects are created
       
   195      * without calling the constructor for that class and the fields
       
   196      * in question are initialized to null.  To support this
       
   197      * capability, any new fields added to Throwable that require
       
   198      * being initialized to a non-null value require a coordinated JVM
       
   199      * change.
       
   200      */
       
   201 
       
   202     /**
   173      * The throwable that caused this throwable to get thrown, or null if this
   203      * The throwable that caused this throwable to get thrown, or null if this
   174      * throwable was not caused by another throwable, or if the causative
   204      * throwable was not caused by another throwable, or if the causative
   175      * throwable is unknown.  If this field is equal to this throwable itself,
   205      * throwable is unknown.  If this field is equal to this throwable itself,
   176      * it indicates that the cause of this throwable has not yet been
   206      * it indicates that the cause of this throwable has not yet been
   177      * initialized.
   207      * initialized.
   186      *
   216      *
   187      * @serial
   217      * @serial
   188      * @since 1.4
   218      * @since 1.4
   189      */
   219      */
   190     private StackTraceElement[] stackTrace;
   220     private StackTraceElement[] stackTrace;
   191     /*
   221 
   192      * This field is lazily initialized on first use or serialization and
   222     // Setting this static field introduces an acceptable
   193      * nulled out when fillInStackTrace is called.
   223     // initialization dependency on a few java.util classes.
   194      */
   224     private static final List<Throwable> SUPPRESSED_SENTINEL =
   195 
   225         Collections.unmodifiableList(new ArrayList<Throwable>(0));
   196     /**
   226 
   197      * The list of suppressed exceptions, as returned by
   227     /**
   198      * {@link #getSuppressedExceptions()}.
   228      * The list of suppressed exceptions, as returned by {@link
       
   229      * #getSuppressed()}.  The list is initialized to a zero-element
       
   230      * unmodifiable sentinel list.  When a serialized Throwable is
       
   231      * read in, if the {@code suppressedExceptions} field points to a
       
   232      * zero-element list, the field is reset to the sentinel value.
   199      *
   233      *
   200      * @serial
   234      * @serial
   201      * @since 1.7
   235      * @since 1.7
   202      */
   236      */
   203     private List<Throwable> suppressedExceptions = null;
   237     private List<Throwable> suppressedExceptions = SUPPRESSED_SENTINEL;
   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      */
       
   213 
   238 
   214     /** Message for trying to suppress a null exception. */
   239     /** Message for trying to suppress a null exception. */
   215     private static final String NULL_CAUSE_MESSAGE = "Cannot suppress a null exception.";
   240     private static final String NULL_CAUSE_MESSAGE = "Cannot suppress a null exception.";
       
   241 
       
   242     /** Message for trying to suppress oneself. */
       
   243     private static final String SELF_SUPPRESSION_MESSAGE = "Self-suppression not permitted";
   216 
   244 
   217     /** Caption  for labeling causative exception stack traces */
   245     /** Caption  for labeling causative exception stack traces */
   218     private static final String CAUSE_CAPTION = "Caused by: ";
   246     private static final String CAUSE_CAPTION = "Caused by: ";
   219 
   247 
   220     /** Caption for labeling suppressed exception stack traces */
   248     /** Caption for labeling suppressed exception stack traces */
   570             StackTraceElement[] trace = getOurStackTrace();
   598             StackTraceElement[] trace = getOurStackTrace();
   571             for (StackTraceElement traceElement : trace)
   599             for (StackTraceElement traceElement : trace)
   572                 s.println("\tat " + traceElement);
   600                 s.println("\tat " + traceElement);
   573 
   601 
   574             // Print suppressed exceptions, if any
   602             // Print suppressed exceptions, if any
   575             for (Throwable se : getSuppressedExceptions())
   603             for (Throwable se : getSuppressed())
   576                 se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu);
   604                 se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu);
   577 
   605 
   578             // Print cause, if any
   606             // Print cause, if any
   579             Throwable ourCause = getCause();
   607             Throwable ourCause = getCause();
   580             if (ourCause != null)
   608             if (ourCause != null)
   611                 s.println(prefix + "\tat " + trace[i]);
   639                 s.println(prefix + "\tat " + trace[i]);
   612             if (framesInCommon != 0)
   640             if (framesInCommon != 0)
   613                 s.println(prefix + "\t... " + framesInCommon + " more");
   641                 s.println(prefix + "\t... " + framesInCommon + " more");
   614 
   642 
   615             // Print suppressed exceptions, if any
   643             // Print suppressed exceptions, if any
   616             for (Throwable se : getSuppressedExceptions())
   644             for (Throwable se : getSuppressed())
   617                 se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION,
   645                 se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION,
   618                                            prefix +"\t", dejaVu);
   646                                            prefix +"\t", dejaVu);
   619 
   647 
   620             // Print cause, if any
   648             // Print cause, if any
   621             Throwable ourCause = getCause();
   649             Throwable ourCause = getCause();
   778      * @throws IndexOutOfBoundsException if {@code index < 0 ||
   806      * @throws IndexOutOfBoundsException if {@code index < 0 ||
   779      *         index >= getStackTraceDepth() }
   807      *         index >= getStackTraceDepth() }
   780      */
   808      */
   781     native StackTraceElement getStackTraceElement(int index);
   809     native StackTraceElement getStackTraceElement(int index);
   782 
   810 
       
   811     /**
       
   812      * Read a {@code Throwable} from a stream, enforcing
       
   813      * well-formedness constraints on fields.  Null entries and
       
   814      * self-pointers are not allowed in the list of {@code
       
   815      * suppressedExceptions}.  Null entries are not allowed for stack
       
   816      * trace elements.
       
   817      *
       
   818      * Note that there are no constraints on the value the {@code
       
   819      * cause} field can hold; both {@code null} and {@code this} are
       
   820      * valid values for the field.
       
   821      */
   783     private void readObject(ObjectInputStream s)
   822     private void readObject(ObjectInputStream s)
   784         throws IOException, ClassNotFoundException {
   823         throws IOException, ClassNotFoundException {
   785         s.defaultReadObject();     // read in all fields
   824         s.defaultReadObject();     // read in all fields
   786         List<Throwable> suppressed = null;
   825         if (suppressedExceptions != null) {
   787         if (suppressedExceptions != null &&
   826             List<Throwable> suppressed = null;
   788             !suppressedExceptions.isEmpty()) { // Copy Throwables to new list
   827             if (suppressedExceptions.isEmpty()) {
   789             suppressed = new ArrayList<Throwable>();
   828                 // Use the sentinel for a zero-length list
   790             for (Throwable t : suppressedExceptions) {
   829                 suppressed = SUPPRESSED_SENTINEL;
   791                 if (t == null)
   830             } else { // Copy Throwables to new list
   792                     throw new NullPointerException(NULL_CAUSE_MESSAGE);
   831                 suppressed = new ArrayList<Throwable>(1);
   793                 suppressed.add(t);
   832                 for (Throwable t : suppressedExceptions) {
       
   833                     // Enforce constraints on suppressed exceptions in
       
   834                     // case of corrupt or malicious stream.
       
   835                     if (t == null)
       
   836                         throw new NullPointerException(NULL_CAUSE_MESSAGE);
       
   837                     if (t == this)
       
   838                         throw new IllegalArgumentException(SELF_SUPPRESSION_MESSAGE);
       
   839                     suppressed.add(t);
       
   840                 }
   794             }
   841             }
   795         }
   842             suppressedExceptions = suppressed;
   796         suppressedExceptions = suppressed;
   843         } // else a null suppressedExceptions field remains null
   797     }
   844 
   798 
   845         if (stackTrace != null) {
       
   846             for (StackTraceElement ste : stackTrace) {
       
   847                 if (ste == null)
       
   848                     throw new NullPointerException("null StackTraceElement in serial stream. ");
       
   849             }
       
   850         } else {
       
   851             // A null stackTrace field in the serial form can result from
       
   852             // an exception serialized without that field in older JDK releases.
       
   853             stackTrace = EMPTY_STACK;
       
   854         }
       
   855 
       
   856     }
       
   857 
       
   858     /**
       
   859      * Write a {@code Throwable} object to a stream.
       
   860      */
   799     private synchronized void writeObject(ObjectOutputStream s)
   861     private synchronized void writeObject(ObjectOutputStream s)
   800         throws IOException
   862         throws IOException {
   801     {
       
   802         getOurStackTrace();  // Ensure that stackTrace field is initialized.
   863         getOurStackTrace();  // Ensure that stackTrace field is initialized.
   803         s.defaultWriteObject();
   864         s.defaultWriteObject();
   804     }
   865     }
   805 
   866 
   806     /**
   867     /**
   807      * Adds the specified exception to the list of exceptions that
   868      * Adds the specified exception to the list of exceptions that
   808      * were suppressed, typically by the {@code try}-with-resources
   869      * were suppressed, typically by the {@code try}-with-resources
   809      * statement, in order to deliver this exception.
   870      * statement, in order to deliver this exception.
       
   871      *
       
   872      * If the first exception to be suppressed is {@code null}, that
       
   873      * indicates suppressed exception information will <em>not</em> be
       
   874      * recorded for this exception.  Subsequent calls to this method
       
   875      * will not record any suppressed exceptions.  Otherwise,
       
   876      * attempting to suppress {@code null} after an exception has
       
   877      * already been successfully suppressed results in a {@code
       
   878      * NullPointerException}.
   810      *
   879      *
   811      * <p>Note that when one exception {@linkplain
   880      * <p>Note that when one exception {@linkplain
   812      * #initCause(Throwable) causes} another exception, the first
   881      * #initCause(Throwable) causes} another exception, the first
   813      * exception is usually caught and then the second exception is
   882      * exception is usually caught and then the second exception is
   814      * thrown in response.  In contrast, when one exception suppresses
   883      * thrown in response.  In contrast, when one exception suppresses
   817      * control flow can only continue with one exception so the second
   886      * control flow can only continue with one exception so the second
   818      * is recorded as a suppressed exception of the first.
   887      * is recorded as a suppressed exception of the first.
   819      *
   888      *
   820      * @param exception the exception to be added to the list of
   889      * @param exception the exception to be added to the list of
   821      *        suppressed exceptions
   890      *        suppressed exceptions
   822      * @throws NullPointerException if {@code exception} is null
       
   823      * @throws IllegalArgumentException if {@code exception} is this
   891      * @throws IllegalArgumentException if {@code exception} is this
   824      *         throwable; a throwable cannot suppress itself.
   892      *         throwable; a throwable cannot suppress itself.
       
   893      * @throws NullPointerException if {@code exception} is null and
       
   894      *         an exception has already been suppressed by this exception
   825      * @since 1.7
   895      * @since 1.7
   826      */
   896      */
   827     public synchronized void addSuppressedException(Throwable exception) {
   897     public final synchronized void addSuppressed(Throwable exception) {
   828         if (exception == null)
       
   829             throw new NullPointerException(NULL_CAUSE_MESSAGE);
       
   830         if (exception == this)
   898         if (exception == this)
   831             throw new IllegalArgumentException("Self-suppression not permitted");
   899             throw new IllegalArgumentException(SELF_SUPPRESSION_MESSAGE);
   832 
   900 
   833         if (suppressedExceptions == null)
   901         if (exception == null) {
   834             suppressedExceptions = new ArrayList<Throwable>();
   902             if (suppressedExceptions == SUPPRESSED_SENTINEL) {
   835         suppressedExceptions.add(exception);
   903                 suppressedExceptions = null; // No suppression information recorded
       
   904                 return;
       
   905             } else
       
   906                 throw new NullPointerException(NULL_CAUSE_MESSAGE);
       
   907         } else {
       
   908             assert exception != null && exception != this;
       
   909 
       
   910             if (suppressedExceptions == null) // Suppressed exceptions not recorded
       
   911                 return;
       
   912 
       
   913             if (suppressedExceptions == SUPPRESSED_SENTINEL)
       
   914                 suppressedExceptions = new ArrayList<Throwable>(1);
       
   915 
       
   916             assert suppressedExceptions != SUPPRESSED_SENTINEL;
       
   917 
       
   918             suppressedExceptions.add(exception);
       
   919         }
   836     }
   920     }
   837 
   921 
   838     private static final Throwable[] EMPTY_THROWABLE_ARRAY = new Throwable[0];
   922     private static final Throwable[] EMPTY_THROWABLE_ARRAY = new Throwable[0];
   839 
   923 
   840     /**
   924     /**
   841      * Returns an array containing all of the exceptions that were
   925      * Returns an array containing all of the exceptions that were
   842      * suppressed, typically by the {@code try}-with-resources
   926      * suppressed, typically by the {@code try}-with-resources
   843      * statement, in order to deliver this exception.
   927      * statement, in order to deliver this exception.
   844      *
   928      *
       
   929      * If no exceptions were suppressed, an empty array is returned.
       
   930      *
   845      * @return an array containing all of the exceptions that were
   931      * @return an array containing all of the exceptions that were
   846      *         suppressed to deliver this exception.
   932      *         suppressed to deliver this exception.
   847      * @since 1.7
   933      * @since 1.7
   848      */
   934      */
   849     public synchronized Throwable[] getSuppressedExceptions() {
   935     public final synchronized Throwable[] getSuppressed() {
   850         if (suppressedExceptions == null)
   936         if (suppressedExceptions == SUPPRESSED_SENTINEL ||
       
   937             suppressedExceptions == null)
   851             return EMPTY_THROWABLE_ARRAY;
   938             return EMPTY_THROWABLE_ARRAY;
   852         else
   939         else
   853             return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY);
   940             return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY);
   854     }
   941     }
   855 }
   942 }