diff -r 700ec2a5d680 -r ec168532bf3f jdk/src/share/classes/java/lang/Throwable.java --- a/jdk/src/share/classes/java/lang/Throwable.java Tue Aug 10 13:15:40 2010 -0700 +++ b/jdk/src/share/classes/java/lang/Throwable.java Thu Aug 12 16:36:49 2010 -0700 @@ -200,7 +200,16 @@ * @serial * @since 1.7 */ - private List suppressedExceptions = Collections.emptyList(); + private List suppressedExceptions = null; + /* + * This field is lazily initialized when the first suppressed + * exception is added. + * + * OutOfMemoryError is preallocated in the VM for better OOM + * diagnosability during VM initialization. Constructor can't + * be not invoked. If a new field to be added in the future must + * be initialized to non-null, it requires a synchronized VM change. + */ /** Message for trying to suppress a null exception. */ private static final String NULL_CAUSE_MESSAGE = "Cannot suppress a null exception."; @@ -329,7 +338,7 @@ * cause is nonexistent or unknown. * @since 1.4 */ - public Throwable getCause() { + public synchronized Throwable getCause() { return (cause==this ? null : cause); } @@ -563,7 +572,7 @@ s.println("\tat " + traceElement); // Print suppressed exceptions, if any - for (Throwable se : suppressedExceptions) + for (Throwable se : getSuppressedExceptions()) se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu); // Print cause, if any @@ -604,7 +613,7 @@ s.println(prefix + "\t... " + framesInCommon + " more"); // Print suppressed exceptions, if any - for (Throwable se : suppressedExceptions) + for (Throwable se : getSuppressedExceptions()) se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, prefix +"\t", dejaVu); @@ -747,7 +756,9 @@ if (defensiveCopy[i] == null) throw new NullPointerException("stackTrace[" + i + "]"); - this.stackTrace = defensiveCopy; + synchronized (this) { + this.stackTrace = defensiveCopy; + } } /** @@ -772,11 +783,11 @@ private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); // read in all fields - List suppressed = Collections.emptyList(); + List suppressed = null; if (suppressedExceptions != null && !suppressedExceptions.isEmpty()) { // Copy Throwables to new list suppressed = new ArrayList(); - for(Throwable t : suppressedExceptions) { + for (Throwable t : suppressedExceptions) { if (t == null) throw new NullPointerException(NULL_CAUSE_MESSAGE); suppressed.add(t); @@ -819,7 +830,7 @@ if (exception == this) throw new IllegalArgumentException("Self-suppression not permitted"); - if (suppressedExceptions.size() == 0) + if (suppressedExceptions == null) suppressedExceptions = new ArrayList(); suppressedExceptions.add(exception); } @@ -835,7 +846,10 @@ * suppressed to deliver this exception. * @since 1.7 */ - public Throwable[] getSuppressedExceptions() { - return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY); + public synchronized Throwable[] getSuppressedExceptions() { + if (suppressedExceptions == null) + return EMPTY_THROWABLE_ARRAY; + else + return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY); } }