KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > lang > Throwable


1 /*
2  * @(#)Throwable.java 1.53 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.lang;
9 import java.io.*;
10
11 /**
12  * The <code>Throwable</code> class is the superclass of all errors and
13  * exceptions in the Java language. Only objects that are instances of this
14  * class (or one of its subclasses) are thrown by the Java Virtual Machine or
15  * can be thrown by the Java <code>throw</code> statement. Similarly, only
16  * this class or one of its subclasses can be the argument type in a
17  * <code>catch</code> clause.
18  *
19  * <p>Instances of two subclasses, {@link java.lang.Error} and
20  * {@link java.lang.Exception}, are conventionally used to indicate
21  * that exceptional situations have occurred. Typically, these instances
22  * are freshly created in the context of the exceptional situation so
23  * as to include relevant information (such as stack trace data).
24  *
25  * <p>A throwable contains a snapshot of the execution stack of its thread at
26  * the time it was created. It can also contain a message string that gives
27  * more information about the error. Finally, it can contain a <i>cause</i>:
28  * another throwable that caused this throwable to get thrown. The cause
29  * facility is new in release 1.4. It is also known as the <i>chained
30  * exception</i> facility, as the cause can, itself, have a cause, and so on,
31  * leading to a "chain" of exceptions, each caused by another.
32  *
33  * <p>One reason that a throwable may have a cause is that the class that
34  * throws it is built atop a lower layered abstraction, and an operation on
35  * the upper layer fails due to a failure in the lower layer. It would be bad
36  * design to let the throwable thrown by the lower layer propagate outward, as
37  * it is generally unrelated to the abstraction provided by the upper layer.
38  * Further, doing so would tie the API of the upper layer to the details of
39  * its implementation, assuming the lower layer's exception was a checked
40  * exception. Throwing a "wrapped exception" (i.e., an exception containing a
41  * cause) allows the upper layer to communicate the details of the failure to
42  * its caller without incurring either of these shortcomings. It preserves
43  * the flexibility to change the implementation of the upper layer without
44  * changing its API (in particular, the set of exceptions thrown by its
45  * methods).
46  *
47  * <p>A second reason that a throwable may have a cause is that the method
48  * that throws it must conform to a general-purpose interface that does not
49  * permit the method to throw the cause directly. For example, suppose
50  * a persistent collection conforms to the {@link java.util.Collection
51  * Collection} interface, and that its persistence is implemented atop
52  * <tt>java.io</tt>. Suppose the internals of the <tt>put</tt> method
53  * can throw an {@link java.io.IOException IOException}. The implementation
54  * can communicate the details of the <tt>IOException</tt> to its caller
55  * while conforming to the <tt>Collection</tt> interface by wrapping the
56  * <tt>IOException</tt> in an appropriate unchecked exception. (The
57  * specification for the persistent collection should indicate that it is
58  * capable of throwing such exceptions.)
59  *
60  * <p>A cause can be associated with a throwable in two ways: via a
61  * constructor that takes the cause as an argument, or via the
62  * {@link #initCause(Throwable)} method. New throwable classes that
63  * wish to allow causes to be associated with them should provide constructors
64  * that take a cause and delegate (perhaps indirectly) to one of the
65  * <tt>Throwable</tt> constructors that takes a cause. For example:
66  * <pre>
67  * try {
68  * lowLevelOp();
69  * } catch (LowLevelException le) {
70  * throw new HighLevelException(le); // Chaining-aware constructor
71  * }
72  * </pre>
73  * Because the <tt>initCause</tt> method is public, it allows a cause to be
74  * associated with any throwable, even a "legacy throwable" whose
75  * implementation predates the addition of the exception chaining mechanism to
76  * <tt>Throwable</tt>. For example:
77  * <pre>
78  * try {
79  * lowLevelOp();
80  * } catch (LowLevelException le) {
81  * throw (HighLevelException)
82                  new HighLevelException().initCause(le); // Legacy constructor
83  * }
84  * </pre>
85  *
86  * <p>Prior to release 1.4, there were many throwables that had their own
87  * non-standard exception chaining mechanisms (
88  * {@link ExceptionInInitializerError}, {@link ClassNotFoundException},
89  * {@link java.lang.reflect.UndeclaredThrowableException},
90  * {@link java.lang.reflect.InvocationTargetException},
91  * {@link java.io.WriteAbortedException},
92  * {@link java.security.PrivilegedActionException},
93  * {@link java.awt.print.PrinterIOException},
94  * {@link java.rmi.RemoteException} and
95  * {@link javax.naming.NamingException}).
96  * All of these throwables have been retrofitted to
97  * use the standard exception chaining mechanism, while continuing to
98  * implement their "legacy" chaining mechanisms for compatibility.
99  *
100  * <p>Further, as of release 1.4, many general purpose <tt>Throwable</tt>
101  * classes (for example {@link Exception}, {@link RuntimeException},
102  * {@link Error}) have been retrofitted with constructors that take
103  * a cause. This was not strictly necessary, due to the existence of the
104  * <tt>initCause</tt> method, but it is more convenient and expressive to
105  * delegate to a constructor that takes a cause.
106  *
107  * <p>By convention, class <code>Throwable</code> and its subclasses have two
108  * constructors, one that takes no arguments and one that takes a
109  * <code>String</code> argument that can be used to produce a detail message.
110  * Further, those subclasses that might likely have a cause associated with
111  * them should have two more constructors, one that takes a
112  * <code>Throwable</code> (the cause), and one that takes a
113  * <code>String</code> (the detail message) and a <code>Throwable</code> (the
114  * cause).
115  *
116  * <p>Also introduced in release 1.4 is the {@link #getStackTrace()} method,
117  * which allows programmatic access to the stack trace information that was
118  * previously available only in text form, via the various forms of the
119  * {@link #printStackTrace()} method. This information has been added to the
120  * <i>serialized representation</i> of this class so <tt>getStackTrace</tt>
121  * and <tt>printStackTrace</tt> will operate properly on a throwable that
122  * was obtained by deserialization.
123  *
124  * @author unascribed
125  * @author Josh Bloch (Added exception chaining and programmatic access to
126  * stack trace in 1.4.)
127  * @version 1.53, 12/19/03
128  * @since JDK1.0
129  */

130 public class Throwable implements Serializable {
131     /** use serialVersionUID from JDK 1.0.2 for interoperability */
132     private static final long serialVersionUID = -3042686055658047285L;
133
134     /**
135      * Native code saves some indication of the stack backtrace in this slot.
136      */

137     private transient Object JavaDoc backtrace;
138
139     /**
140      * Specific details about the Throwable. For example, for
141      * <tt>FileNotFoundException</tt>, this contains the name of
142      * the file that could not be found.
143      *
144      * @serial
145      */

146     private String JavaDoc detailMessage;
147
148     /**
149      * The throwable that caused this throwable to get thrown, or null if this
150      * throwable was not caused by another throwable, or if the causative
151      * throwable is unknown. If this field is equal to this throwable itself,
152      * it indicates that the cause of this throwable has not yet been
153      * initialized.
154      *
155      * @serial
156      * @since 1.4
157      */

158     private Throwable JavaDoc cause = this;
159
160     /**
161      * The stack trace, as returned by {@link #getStackTrace()}.
162      *
163      * @serial
164      * @since 1.4
165      */

166     private StackTraceElement JavaDoc[] stackTrace;
167     /*
168      * This field is lazily initialized on first use or serialization and
169      * nulled out when fillInStackTrace is called.
170      */

171
172     /**
173      * Constructs a new throwable with <code>null</code> as its detail message.
174      * The cause is not initialized, and may subsequently be initialized by a
175      * call to {@link #initCause}.
176      *
177      * <p>The {@link #fillInStackTrace()} method is called to initialize
178      * the stack trace data in the newly created throwable.
179      */

180     public Throwable() {
181         fillInStackTrace();
182     }
183
184     /**
185      * Constructs a new throwable with the specified detail message. The
186      * cause is not initialized, and may subsequently be initialized by
187      * a call to {@link #initCause}.
188      *
189      * <p>The {@link #fillInStackTrace()} method is called to initialize
190      * the stack trace data in the newly created throwable.
191      *
192      * @param message the detail message. The detail message is saved for
193      * later retrieval by the {@link #getMessage()} method.
194      */

195     public Throwable(String JavaDoc message) {
196         fillInStackTrace();
197         detailMessage = message;
198     }
199
200     /**
201      * Constructs a new throwable with the specified detail message and
202      * cause. <p>Note that the detail message associated with
203      * <code>cause</code> is <i>not</i> automatically incorporated in
204      * this throwable's detail message.
205      *
206      * <p>The {@link #fillInStackTrace()} method is called to initialize
207      * the stack trace data in the newly created throwable.
208      *
209      * @param message the detail message (which is saved for later retrieval
210      * by the {@link #getMessage()} method).
211      * @param cause the cause (which is saved for later retrieval by the
212      * {@link #getCause()} method). (A <tt>null</tt> value is
213      * permitted, and indicates that the cause is nonexistent or
214      * unknown.)
215      * @since 1.4
216      */

217     public Throwable(String JavaDoc message, Throwable JavaDoc cause) {
218         fillInStackTrace();
219         detailMessage = message;
220         this.cause = cause;
221     }
222
223     /**
224      * Constructs a new throwable with the specified cause and a detail
225      * message of <tt>(cause==null ? null : cause.toString())</tt> (which
226      * typically contains the class and detail message of <tt>cause</tt>).
227      * This constructor is useful for throwables that are little more than
228      * wrappers for other throwables (for example, {@link
229      * java.security.PrivilegedActionException}).
230      *
231      * <p>The {@link #fillInStackTrace()} method is called to initialize
232      * the stack trace data in the newly created throwable.
233      *
234      * @param cause the cause (which is saved for later retrieval by the
235      * {@link #getCause()} method). (A <tt>null</tt> value is
236      * permitted, and indicates that the cause is nonexistent or
237      * unknown.)
238      * @since 1.4
239      */

240     public Throwable(Throwable JavaDoc cause) {
241         fillInStackTrace();
242         detailMessage = (cause==null ? null : cause.toString());
243         this.cause = cause;
244     }
245
246     /**
247      * Returns the detail message string of this throwable.
248      *
249      * @return the detail message string of this <tt>Throwable</tt> instance
250      * (which may be <tt>null</tt>).
251      */

252     public String JavaDoc getMessage() {
253         return detailMessage;
254     }
255
256     /**
257      * Creates a localized description of this throwable.
258      * Subclasses may override this method in order to produce a
259      * locale-specific message. For subclasses that do not override this
260      * method, the default implementation returns the same result as
261      * <code>getMessage()</code>.
262      *
263      * @return The localized description of this throwable.
264      * @since JDK1.1
265      */

266     public String JavaDoc getLocalizedMessage() {
267         return getMessage();
268     }
269
270     /**
271      * Returns the cause of this throwable or <code>null</code> if the
272      * cause is nonexistent or unknown. (The cause is the throwable that
273      * caused this throwable to get thrown.)
274      *
275      * <p>This implementation returns the cause that was supplied via one of
276      * the constructors requiring a <tt>Throwable</tt>, or that was set after
277      * creation with the {@link #initCause(Throwable)} method. While it is
278      * typically unnecessary to override this method, a subclass can override
279      * it to return a cause set by some other means. This is appropriate for
280      * a "legacy chained throwable" that predates the addition of chained
281      * exceptions to <tt>Throwable</tt>. Note that it is <i>not</i>
282      * necessary to override any of the <tt>PrintStackTrace</tt> methods,
283      * all of which invoke the <tt>getCause</tt> method to determine the
284      * cause of a throwable.
285      *
286      * @return the cause of this throwable or <code>null</code> if the
287      * cause is nonexistent or unknown.
288      * @since 1.4
289      */

290     public Throwable JavaDoc getCause() {
291         return (cause==this ? null : cause);
292     }
293
294     /**
295      * Initializes the <i>cause</i> of this throwable to the specified value.
296      * (The cause is the throwable that caused this throwable to get thrown.)
297      *
298      * <p>This method can be called at most once. It is generally called from
299      * within the constructor, or immediately after creating the
300      * throwable. If this throwable was created
301      * with {@link #Throwable(Throwable)} or
302      * {@link #Throwable(String,Throwable)}, this method cannot be called
303      * even once.
304      *
305      * @param cause the cause (which is saved for later retrieval by the
306      * {@link #getCause()} method). (A <tt>null</tt> value is
307      * permitted, and indicates that the cause is nonexistent or
308      * unknown.)
309      * @return a reference to this <code>Throwable</code> instance.
310      * @throws IllegalArgumentException if <code>cause</code> is this
311      * throwable. (A throwable cannot be its own cause.)
312      * @throws IllegalStateException if this throwable was
313      * created with {@link #Throwable(Throwable)} or
314      * {@link #Throwable(String,Throwable)}, or this method has already
315      * been called on this throwable.
316      * @since 1.4
317      */

318     public synchronized Throwable JavaDoc initCause(Throwable JavaDoc cause) {
319         if (this.cause != this)
320             throw new IllegalStateException JavaDoc("Can't overwrite cause");
321         if (cause == this)
322             throw new IllegalArgumentException JavaDoc("Self-causation not permitted");
323         this.cause = cause;
324         return this;
325     }
326
327     /**
328      * Returns a short description of this throwable.
329      * If this <code>Throwable</code> object was created with a non-null detail
330      * message string, then the result is the concatenation of three strings:
331      * <ul>
332      * <li>The name of the actual class of this object
333      * <li>": " (a colon and a space)
334      * <li>The result of the {@link #getMessage} method for this object
335      * </ul>
336      * If this <code>Throwable</code> object was created with a <tt>null</tt>
337      * detail message string, then the name of the actual class of this object
338      * is returned.
339      *
340      * @return a string representation of this throwable.
341      */

342     public String JavaDoc toString() {
343         String JavaDoc s = getClass().getName();
344         String JavaDoc message = getLocalizedMessage();
345         return (message != null) ? (s + ": " + message) : s;
346     }
347
348     /**
349      * Prints this throwable and its backtrace to the
350      * standard error stream. This method prints a stack trace for this
351      * <code>Throwable</code> object on the error output stream that is
352      * the value of the field <code>System.err</code>. The first line of
353      * output contains the result of the {@link #toString()} method for
354      * this object. Remaining lines represent data previously recorded by
355      * the method {@link #fillInStackTrace()}. The format of this
356      * information depends on the implementation, but the following
357      * example may be regarded as typical:
358      * <blockquote><pre>
359      * java.lang.NullPointerException
360      * at MyClass.mash(MyClass.java:9)
361      * at MyClass.crunch(MyClass.java:6)
362      * at MyClass.main(MyClass.java:3)
363      * </pre></blockquote>
364      * This example was produced by running the program:
365      * <pre>
366      * class MyClass {
367      * public static void main(String[] args) {
368      * crunch(null);
369      * }
370      * static void crunch(int[] a) {
371      * mash(a);
372      * }
373      * static void mash(int[] b) {
374      * System.out.println(b[0]);
375      * }
376      * }
377      * </pre>
378      * The backtrace for a throwable with an initialized, non-null cause
379      * should generally include the backtrace for the cause. The format
380      * of this information depends on the implementation, but the following
381      * example may be regarded as typical:
382      * <pre>
383      * HighLevelException: MidLevelException: LowLevelException
384      * at Junk.a(Junk.java:13)
385      * at Junk.main(Junk.java:4)
386      * Caused by: MidLevelException: LowLevelException
387      * at Junk.c(Junk.java:23)
388      * at Junk.b(Junk.java:17)
389      * at Junk.a(Junk.java:11)
390      * ... 1 more
391      * Caused by: LowLevelException
392      * at Junk.e(Junk.java:30)
393      * at Junk.d(Junk.java:27)
394      * at Junk.c(Junk.java:21)
395      * ... 3 more
396      * </pre>
397      * Note the presence of lines containing the characters <tt>"..."</tt>.
398      * These lines indicate that the remainder of the stack trace for this
399      * exception matches the indicated number of frames from the bottom of the
400      * stack trace of the exception that was caused by this exception (the
401      * "enclosing" exception). This shorthand can greatly reduce the length
402      * of the output in the common case where a wrapped exception is thrown
403      * from same method as the "causative exception" is caught. The above
404      * example was produced by running the program:
405      * <pre>
406      * public class Junk {
407      * public static void main(String args[]) {
408      * try {
409      * a();
410      * } catch(HighLevelException e) {
411      * e.printStackTrace();
412      * }
413      * }
414      * static void a() throws HighLevelException {
415      * try {
416      * b();
417      * } catch(MidLevelException e) {
418      * throw new HighLevelException(e);
419      * }
420      * }
421      * static void b() throws MidLevelException {
422      * c();
423      * }
424      * static void c() throws MidLevelException {
425      * try {
426      * d();
427      * } catch(LowLevelException e) {
428      * throw new MidLevelException(e);
429      * }
430      * }
431      * static void d() throws LowLevelException {
432      * e();
433      * }
434      * static void e() throws LowLevelException {
435      * throw new LowLevelException();
436      * }
437      * }
438      *
439      * class HighLevelException extends Exception {
440      * HighLevelException(Throwable cause) { super(cause); }
441      * }
442      *
443      * class MidLevelException extends Exception {
444      * MidLevelException(Throwable cause) { super(cause); }
445      * }
446      *
447      * class LowLevelException extends Exception {
448      * }
449      * </pre>
450      */

451     public void printStackTrace() {
452         printStackTrace(System.err);
453     }
454
455     /**
456      * Prints this throwable and its backtrace to the specified print stream.
457      *
458      * @param s <code>PrintStream</code> to use for output
459      */

460     public void printStackTrace(PrintStream s) {
461         synchronized (s) {
462             s.println(this);
463             StackTraceElement JavaDoc[] trace = getOurStackTrace();
464             for (int i=0; i < trace.length; i++)
465                 s.println("\tat " + trace[i]);
466
467             Throwable JavaDoc ourCause = getCause();
468             if (ourCause != null)
469                 ourCause.printStackTraceAsCause(s, trace);
470         }
471     }
472
473     /**
474      * Print our stack trace as a cause for the specified stack trace.
475      */

476     private void printStackTraceAsCause(PrintStream s,
477                                         StackTraceElement JavaDoc[] causedTrace)
478     {
479         // assert Thread.holdsLock(s);
480

481         // Compute number of frames in common between this and caused
482
StackTraceElement JavaDoc[] trace = getOurStackTrace();
483         int m = trace.length-1, n = causedTrace.length-1;
484         while (m >= 0 && n >=0 && trace[m].equals(causedTrace[n])) {
485             m--; n--;
486         }
487         int framesInCommon = trace.length - 1 - m;
488
489         s.println("Caused by: " + this);
490         for (int i=0; i <= m; i++)
491             s.println("\tat " + trace[i]);
492         if (framesInCommon != 0)
493             s.println("\t... " + framesInCommon + " more");
494
495         // Recurse if we have a cause
496
Throwable JavaDoc ourCause = getCause();
497         if (ourCause != null)
498             ourCause.printStackTraceAsCause(s, trace);
499     }
500
501     /**
502      * Prints this throwable and its backtrace to the specified
503      * print writer.
504      *
505      * @param s <code>PrintWriter</code> to use for output
506      * @since JDK1.1
507      */

508     public void printStackTrace(PrintWriter s) {
509         synchronized (s) {
510             s.println(this);
511             StackTraceElement JavaDoc[] trace = getOurStackTrace();
512             for (int i=0; i < trace.length; i++)
513                 s.println("\tat " + trace[i]);
514
515             Throwable JavaDoc ourCause = getCause();
516             if (ourCause != null)
517                 ourCause.printStackTraceAsCause(s, trace);
518         }
519     }
520
521     /**
522      * Print our stack trace as a cause for the specified stack trace.
523      */

524     private void printStackTraceAsCause(PrintWriter s,
525                                         StackTraceElement JavaDoc[] causedTrace)
526     {
527         // assert Thread.holdsLock(s);
528

529         // Compute number of frames in common between this and caused
530
StackTraceElement JavaDoc[] trace = getOurStackTrace();
531         int m = trace.length-1, n = causedTrace.length-1;
532         while (m >= 0 && n >=0 && trace[m].equals(causedTrace[n])) {
533             m--; n--;
534         }
535         int framesInCommon = trace.length - 1 - m;
536
537         s.println("Caused by: " + this);
538         for (int i=0; i <= m; i++)
539             s.println("\tat " + trace[i]);
540         if (framesInCommon != 0)
541             s.println("\t... " + framesInCommon + " more");
542
543         // Recurse if we have a cause
544
Throwable JavaDoc ourCause = getCause();
545         if (ourCause != null)
546             ourCause.printStackTraceAsCause(s, trace);
547     }
548
549     /**
550      * Fills in the execution stack trace. This method records within this
551      * <code>Throwable</code> object information about the current state of
552      * the stack frames for the current thread.
553      *
554      * @return a reference to this <code>Throwable</code> instance.
555      * @see java.lang.Throwable#printStackTrace()
556      */

557     public synchronized native Throwable JavaDoc fillInStackTrace();
558
559     /**
560      * Provides programmatic access to the stack trace information printed by
561      * {@link #printStackTrace()}. Returns an array of stack trace elements,
562      * each representing one stack frame. The zeroth element of the array
563      * (assuming the array's length is non-zero) represents the top of the
564      * stack, which is the last method invocation in the sequence. Typically,
565      * this is the point at which this throwable was created and thrown.
566      * The last element of the array (assuming the array's length is non-zero)
567      * represents the bottom of the stack, which is the first method invocation
568      * in the sequence.
569      *
570      * <p>Some virtual machines may, under some circumstances, omit one
571      * or more stack frames from the stack trace. In the extreme case,
572      * a virtual machine that has no stack trace information concerning
573      * this throwable is permitted to return a zero-length array from this
574      * method. Generally speaking, the array returned by this method will
575      * contain one element for every frame that would be printed by
576      * <tt>printStackTrace</tt>.
577      *
578      * @return an array of stack trace elements representing the stack trace
579      * pertaining to this throwable.
580      * @since 1.4
581      */

582     public StackTraceElement JavaDoc[] getStackTrace() {
583         return (StackTraceElement JavaDoc[]) getOurStackTrace().clone();
584     }
585
586     private synchronized StackTraceElement JavaDoc[] getOurStackTrace() {
587         // Initialize stack trace if this is the first call to this method
588
if (stackTrace == null) {
589             int depth = getStackTraceDepth();
590             stackTrace = new StackTraceElement JavaDoc[depth];
591             for (int i=0; i < depth; i++)
592                 stackTrace[i] = getStackTraceElement(i);
593         }
594         return stackTrace;
595     }
596
597     /**
598      * Sets the stack trace elements that will be returned by
599      * {@link #getStackTrace()} and printed by {@link #printStackTrace()}
600      * and related methods.
601      *
602      * This method, which is designed for use by RPC frameworks and other
603      * advanced systems, allows the client to override the default
604      * stack trace that is either generated by {@link #fillInStackTrace()}
605      * when a throwable is constructed or deserialized when a throwable is
606      * read from a serialization stream.
607      *
608      * @param stackTrace the stack trace elements to be associated with
609      * this <code>Throwable</code>. The specified array is copied by this
610      * call; changes in the specified array after the method invocation
611      * returns will have no affect on this <code>Throwable</code>'s stack
612      * trace.
613      *
614      * @throws NullPointerException if <code>stackTrace</code> is
615      * <code>null</code>, or if any of the elements of
616      * <code>stackTrace</code> are <code>null</code>
617      *
618      * @since 1.4
619      */

620     public void setStackTrace(StackTraceElement JavaDoc[] stackTrace) {
621         StackTraceElement JavaDoc[] defensiveCopy =
622             (StackTraceElement JavaDoc[]) stackTrace.clone();
623         for (int i = 0; i < defensiveCopy.length; i++)
624             if (defensiveCopy[i] == null)
625                 throw new NullPointerException JavaDoc("stackTrace[" + i + "]");
626
627         this.stackTrace = defensiveCopy;
628     }
629
630     /**
631      * Returns the number of elements in the stack trace (or 0 if the stack
632      * trace is unavailable).
633      */

634     private native int getStackTraceDepth();
635
636     /**
637      * Returns the specified element of the stack trace.
638      *
639      * @param index index of the element to return.
640      * @throws IndexOutOfBoundsException if <tt>index %lt; 0 ||
641      * index &gt;= getStackTraceDepth() </tt>
642      */

643     private native StackTraceElement JavaDoc getStackTraceElement(int index);
644
645     private synchronized void writeObject(java.io.ObjectOutputStream JavaDoc s)
646         throws IOException
647     {
648         getOurStackTrace(); // Ensure that stackTrace field is initialized.
649
s.defaultWriteObject();
650     }
651 }
652
Popular Tags