001: /*
002: * Copyright 1994-2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package java.lang;
027:
028: import java.io.*;
029:
030: /**
031: * The <code>Throwable</code> class is the superclass of all errors and
032: * exceptions in the Java language. Only objects that are instances of this
033: * class (or one of its subclasses) are thrown by the Java Virtual Machine or
034: * can be thrown by the Java <code>throw</code> statement. Similarly, only
035: * this class or one of its subclasses can be the argument type in a
036: * <code>catch</code> clause.
037: *
038: * <p>Instances of two subclasses, {@link java.lang.Error} and
039: * {@link java.lang.Exception}, are conventionally used to indicate
040: * that exceptional situations have occurred. Typically, these instances
041: * are freshly created in the context of the exceptional situation so
042: * as to include relevant information (such as stack trace data).
043: *
044: * <p>A throwable contains a snapshot of the execution stack of its thread at
045: * the time it was created. It can also contain a message string that gives
046: * more information about the error. Finally, it can contain a <i>cause</i>:
047: * another throwable that caused this throwable to get thrown. The cause
048: * facility is new in release 1.4. It is also known as the <i>chained
049: * exception</i> facility, as the cause can, itself, have a cause, and so on,
050: * leading to a "chain" of exceptions, each caused by another.
051: *
052: * <p>One reason that a throwable may have a cause is that the class that
053: * throws it is built atop a lower layered abstraction, and an operation on
054: * the upper layer fails due to a failure in the lower layer. It would be bad
055: * design to let the throwable thrown by the lower layer propagate outward, as
056: * it is generally unrelated to the abstraction provided by the upper layer.
057: * Further, doing so would tie the API of the upper layer to the details of
058: * its implementation, assuming the lower layer's exception was a checked
059: * exception. Throwing a "wrapped exception" (i.e., an exception containing a
060: * cause) allows the upper layer to communicate the details of the failure to
061: * its caller without incurring either of these shortcomings. It preserves
062: * the flexibility to change the implementation of the upper layer without
063: * changing its API (in particular, the set of exceptions thrown by its
064: * methods).
065: *
066: * <p>A second reason that a throwable may have a cause is that the method
067: * that throws it must conform to a general-purpose interface that does not
068: * permit the method to throw the cause directly. For example, suppose
069: * a persistent collection conforms to the {@link java.util.Collection
070: * Collection} interface, and that its persistence is implemented atop
071: * <tt>java.io</tt>. Suppose the internals of the <tt>add</tt> method
072: * can throw an {@link java.io.IOException IOException}. The implementation
073: * can communicate the details of the <tt>IOException</tt> to its caller
074: * while conforming to the <tt>Collection</tt> interface by wrapping the
075: * <tt>IOException</tt> in an appropriate unchecked exception. (The
076: * specification for the persistent collection should indicate that it is
077: * capable of throwing such exceptions.)
078: *
079: * <p>A cause can be associated with a throwable in two ways: via a
080: * constructor that takes the cause as an argument, or via the
081: * {@link #initCause(Throwable)} method. New throwable classes that
082: * wish to allow causes to be associated with them should provide constructors
083: * that take a cause and delegate (perhaps indirectly) to one of the
084: * <tt>Throwable</tt> constructors that takes a cause. For example:
085: * <pre>
086: * try {
087: * lowLevelOp();
088: * } catch (LowLevelException le) {
089: * throw new HighLevelException(le); // Chaining-aware constructor
090: * }
091: * </pre>
092: * Because the <tt>initCause</tt> method is public, it allows a cause to be
093: * associated with any throwable, even a "legacy throwable" whose
094: * implementation predates the addition of the exception chaining mechanism to
095: * <tt>Throwable</tt>. For example:
096: * <pre>
097: * try {
098: * lowLevelOp();
099: * } catch (LowLevelException le) {
100: * throw (HighLevelException)
101: new HighLevelException().initCause(le); // Legacy constructor
102: * }
103: * </pre>
104: *
105: * <p>Prior to release 1.4, there were many throwables that had their own
106: * non-standard exception chaining mechanisms (
107: * {@link ExceptionInInitializerError}, {@link ClassNotFoundException},
108: * {@link java.lang.reflect.UndeclaredThrowableException},
109: * {@link java.lang.reflect.InvocationTargetException},
110: * {@link java.io.WriteAbortedException},
111: * {@link java.security.PrivilegedActionException},
112: * {@link java.awt.print.PrinterIOException},
113: * {@link java.rmi.RemoteException} and
114: * {@link javax.naming.NamingException}).
115: * All of these throwables have been retrofitted to
116: * use the standard exception chaining mechanism, while continuing to
117: * implement their "legacy" chaining mechanisms for compatibility.
118: *
119: * <p>Further, as of release 1.4, many general purpose <tt>Throwable</tt>
120: * classes (for example {@link Exception}, {@link RuntimeException},
121: * {@link Error}) have been retrofitted with constructors that take
122: * a cause. This was not strictly necessary, due to the existence of the
123: * <tt>initCause</tt> method, but it is more convenient and expressive to
124: * delegate to a constructor that takes a cause.
125: *
126: * <p>By convention, class <code>Throwable</code> and its subclasses have two
127: * constructors, one that takes no arguments and one that takes a
128: * <code>String</code> argument that can be used to produce a detail message.
129: * Further, those subclasses that might likely have a cause associated with
130: * them should have two more constructors, one that takes a
131: * <code>Throwable</code> (the cause), and one that takes a
132: * <code>String</code> (the detail message) and a <code>Throwable</code> (the
133: * cause).
134: *
135: * <p>Also introduced in release 1.4 is the {@link #getStackTrace()} method,
136: * which allows programmatic access to the stack trace information that was
137: * previously available only in text form, via the various forms of the
138: * {@link #printStackTrace()} method. This information has been added to the
139: * <i>serialized representation</i> of this class so <tt>getStackTrace</tt>
140: * and <tt>printStackTrace</tt> will operate properly on a throwable that
141: * was obtained by deserialization.
142: *
143: * @author unascribed
144: * @author Josh Bloch (Added exception chaining and programmatic access to
145: * stack trace in 1.4.)
146: * @version 1.62, 05/05/07
147: * @since JDK1.0
148: */
149: public class Throwable implements Serializable {
150: /** use serialVersionUID from JDK 1.0.2 for interoperability */
151: private static final long serialVersionUID = -3042686055658047285L;
152:
153: /**
154: * Native code saves some indication of the stack backtrace in this slot.
155: */
156: private transient Object backtrace;
157:
158: /**
159: * Specific details about the Throwable. For example, for
160: * <tt>FileNotFoundException</tt>, this contains the name of
161: * the file that could not be found.
162: *
163: * @serial
164: */
165: private String detailMessage;
166:
167: /**
168: * The throwable that caused this throwable to get thrown, or null if this
169: * throwable was not caused by another throwable, or if the causative
170: * throwable is unknown. If this field is equal to this throwable itself,
171: * it indicates that the cause of this throwable has not yet been
172: * initialized.
173: *
174: * @serial
175: * @since 1.4
176: */
177: private Throwable cause = this ;
178:
179: /**
180: * The stack trace, as returned by {@link #getStackTrace()}.
181: *
182: * @serial
183: * @since 1.4
184: */
185: private StackTraceElement[] stackTrace;
186:
187: /*
188: * This field is lazily initialized on first use or serialization and
189: * nulled out when fillInStackTrace is called.
190: */
191:
192: /**
193: * Constructs a new throwable with <code>null</code> as its detail message.
194: * The cause is not initialized, and may subsequently be initialized by a
195: * call to {@link #initCause}.
196: *
197: * <p>The {@link #fillInStackTrace()} method is called to initialize
198: * the stack trace data in the newly created throwable.
199: */
200: public Throwable() {
201: fillInStackTrace();
202: }
203:
204: /**
205: * Constructs a new throwable with the specified detail message. The
206: * cause is not initialized, and may subsequently be initialized by
207: * a call to {@link #initCause}.
208: *
209: * <p>The {@link #fillInStackTrace()} method is called to initialize
210: * the stack trace data in the newly created throwable.
211: *
212: * @param message the detail message. The detail message is saved for
213: * later retrieval by the {@link #getMessage()} method.
214: */
215: public Throwable(String message) {
216: fillInStackTrace();
217: detailMessage = message;
218: }
219:
220: /**
221: * Constructs a new throwable with the specified detail message and
222: * cause. <p>Note that the detail message associated with
223: * <code>cause</code> is <i>not</i> automatically incorporated in
224: * this throwable's detail message.
225: *
226: * <p>The {@link #fillInStackTrace()} method is called to initialize
227: * the stack trace data in the newly created throwable.
228: *
229: * @param message the detail message (which is saved for later retrieval
230: * by the {@link #getMessage()} method).
231: * @param cause the cause (which is saved for later retrieval by the
232: * {@link #getCause()} method). (A <tt>null</tt> value is
233: * permitted, and indicates that the cause is nonexistent or
234: * unknown.)
235: * @since 1.4
236: */
237: public Throwable(String message, Throwable cause) {
238: fillInStackTrace();
239: detailMessage = message;
240: this .cause = cause;
241: }
242:
243: /**
244: * Constructs a new throwable with the specified cause and a detail
245: * message of <tt>(cause==null ? null : cause.toString())</tt> (which
246: * typically contains the class and detail message of <tt>cause</tt>).
247: * This constructor is useful for throwables that are little more than
248: * wrappers for other throwables (for example, {@link
249: * java.security.PrivilegedActionException}).
250: *
251: * <p>The {@link #fillInStackTrace()} method is called to initialize
252: * the stack trace data in the newly created throwable.
253: *
254: * @param cause the cause (which is saved for later retrieval by the
255: * {@link #getCause()} method). (A <tt>null</tt> value is
256: * permitted, and indicates that the cause is nonexistent or
257: * unknown.)
258: * @since 1.4
259: */
260: public Throwable(Throwable cause) {
261: fillInStackTrace();
262: detailMessage = (cause == null ? null : cause.toString());
263: this .cause = cause;
264: }
265:
266: /**
267: * Returns the detail message string of this throwable.
268: *
269: * @return the detail message string of this <tt>Throwable</tt> instance
270: * (which may be <tt>null</tt>).
271: */
272: public String getMessage() {
273: return detailMessage;
274: }
275:
276: /**
277: * Creates a localized description of this throwable.
278: * Subclasses may override this method in order to produce a
279: * locale-specific message. For subclasses that do not override this
280: * method, the default implementation returns the same result as
281: * <code>getMessage()</code>.
282: *
283: * @return The localized description of this throwable.
284: * @since JDK1.1
285: */
286: public String getLocalizedMessage() {
287: return getMessage();
288: }
289:
290: /**
291: * Returns the cause of this throwable or <code>null</code> if the
292: * cause is nonexistent or unknown. (The cause is the throwable that
293: * caused this throwable to get thrown.)
294: *
295: * <p>This implementation returns the cause that was supplied via one of
296: * the constructors requiring a <tt>Throwable</tt>, or that was set after
297: * creation with the {@link #initCause(Throwable)} method. While it is
298: * typically unnecessary to override this method, a subclass can override
299: * it to return a cause set by some other means. This is appropriate for
300: * a "legacy chained throwable" that predates the addition of chained
301: * exceptions to <tt>Throwable</tt>. Note that it is <i>not</i>
302: * necessary to override any of the <tt>PrintStackTrace</tt> methods,
303: * all of which invoke the <tt>getCause</tt> method to determine the
304: * cause of a throwable.
305: *
306: * @return the cause of this throwable or <code>null</code> if the
307: * cause is nonexistent or unknown.
308: * @since 1.4
309: */
310: public Throwable getCause() {
311: return (cause == this ? null : cause);
312: }
313:
314: /**
315: * Initializes the <i>cause</i> of this throwable to the specified value.
316: * (The cause is the throwable that caused this throwable to get thrown.)
317: *
318: * <p>This method can be called at most once. It is generally called from
319: * within the constructor, or immediately after creating the
320: * throwable. If this throwable was created
321: * with {@link #Throwable(Throwable)} or
322: * {@link #Throwable(String,Throwable)}, this method cannot be called
323: * even once.
324: *
325: * @param cause the cause (which is saved for later retrieval by the
326: * {@link #getCause()} method). (A <tt>null</tt> value is
327: * permitted, and indicates that the cause is nonexistent or
328: * unknown.)
329: * @return a reference to this <code>Throwable</code> instance.
330: * @throws IllegalArgumentException if <code>cause</code> is this
331: * throwable. (A throwable cannot be its own cause.)
332: * @throws IllegalStateException if this throwable was
333: * created with {@link #Throwable(Throwable)} or
334: * {@link #Throwable(String,Throwable)}, or this method has already
335: * been called on this throwable.
336: * @since 1.4
337: */
338: public synchronized Throwable initCause(Throwable cause) {
339: if (this .cause != this )
340: throw new IllegalStateException("Can't overwrite cause");
341: if (cause == this )
342: throw new IllegalArgumentException(
343: "Self-causation not permitted");
344: this .cause = cause;
345: return this ;
346: }
347:
348: /**
349: * Returns a short description of this throwable.
350: * The result is the concatenation of:
351: * <ul>
352: * <li> the {@linkplain Class#getName() name} of the class of this object
353: * <li> ": " (a colon and a space)
354: * <li> the result of invoking this object's {@link #getLocalizedMessage}
355: * method
356: * </ul>
357: * If <tt>getLocalizedMessage</tt> returns <tt>null</tt>, then just
358: * the class name is returned.
359: *
360: * @return a string representation of this throwable.
361: */
362: public String toString() {
363: String s = getClass().getName();
364: String message = getLocalizedMessage();
365: return (message != null) ? (s + ": " + message) : s;
366: }
367:
368: /**
369: * Prints this throwable and its backtrace to the
370: * standard error stream. This method prints a stack trace for this
371: * <code>Throwable</code> object on the error output stream that is
372: * the value of the field <code>System.err</code>. The first line of
373: * output contains the result of the {@link #toString()} method for
374: * this object. Remaining lines represent data previously recorded by
375: * the method {@link #fillInStackTrace()}. The format of this
376: * information depends on the implementation, but the following
377: * example may be regarded as typical:
378: * <blockquote><pre>
379: * java.lang.NullPointerException
380: * at MyClass.mash(MyClass.java:9)
381: * at MyClass.crunch(MyClass.java:6)
382: * at MyClass.main(MyClass.java:3)
383: * </pre></blockquote>
384: * This example was produced by running the program:
385: * <pre>
386: * class MyClass {
387: * public static void main(String[] args) {
388: * crunch(null);
389: * }
390: * static void crunch(int[] a) {
391: * mash(a);
392: * }
393: * static void mash(int[] b) {
394: * System.out.println(b[0]);
395: * }
396: * }
397: * </pre>
398: * The backtrace for a throwable with an initialized, non-null cause
399: * should generally include the backtrace for the cause. The format
400: * of this information depends on the implementation, but the following
401: * example may be regarded as typical:
402: * <pre>
403: * HighLevelException: MidLevelException: LowLevelException
404: * at Junk.a(Junk.java:13)
405: * at Junk.main(Junk.java:4)
406: * Caused by: MidLevelException: LowLevelException
407: * at Junk.c(Junk.java:23)
408: * at Junk.b(Junk.java:17)
409: * at Junk.a(Junk.java:11)
410: * ... 1 more
411: * Caused by: LowLevelException
412: * at Junk.e(Junk.java:30)
413: * at Junk.d(Junk.java:27)
414: * at Junk.c(Junk.java:21)
415: * ... 3 more
416: * </pre>
417: * Note the presence of lines containing the characters <tt>"..."</tt>.
418: * These lines indicate that the remainder of the stack trace for this
419: * exception matches the indicated number of frames from the bottom of the
420: * stack trace of the exception that was caused by this exception (the
421: * "enclosing" exception). This shorthand can greatly reduce the length
422: * of the output in the common case where a wrapped exception is thrown
423: * from same method as the "causative exception" is caught. The above
424: * example was produced by running the program:
425: * <pre>
426: * public class Junk {
427: * public static void main(String args[]) {
428: * try {
429: * a();
430: * } catch(HighLevelException e) {
431: * e.printStackTrace();
432: * }
433: * }
434: * static void a() throws HighLevelException {
435: * try {
436: * b();
437: * } catch(MidLevelException e) {
438: * throw new HighLevelException(e);
439: * }
440: * }
441: * static void b() throws MidLevelException {
442: * c();
443: * }
444: * static void c() throws MidLevelException {
445: * try {
446: * d();
447: * } catch(LowLevelException e) {
448: * throw new MidLevelException(e);
449: * }
450: * }
451: * static void d() throws LowLevelException {
452: * e();
453: * }
454: * static void e() throws LowLevelException {
455: * throw new LowLevelException();
456: * }
457: * }
458: *
459: * class HighLevelException extends Exception {
460: * HighLevelException(Throwable cause) { super(cause); }
461: * }
462: *
463: * class MidLevelException extends Exception {
464: * MidLevelException(Throwable cause) { super(cause); }
465: * }
466: *
467: * class LowLevelException extends Exception {
468: * }
469: * </pre>
470: */
471: public void printStackTrace() {
472: printStackTrace(System.err);
473: }
474:
475: /**
476: * Prints this throwable and its backtrace to the specified print stream.
477: *
478: * @param s <code>PrintStream</code> to use for output
479: */
480: public void printStackTrace(PrintStream s) {
481: synchronized (s) {
482: s.println(this );
483: StackTraceElement[] trace = getOurStackTrace();
484: for (int i = 0; i < trace.length; i++)
485: s.println("\tat " + trace[i]);
486:
487: Throwable ourCause = getCause();
488: if (ourCause != null)
489: ourCause.printStackTraceAsCause(s, trace);
490: }
491: }
492:
493: /**
494: * Print our stack trace as a cause for the specified stack trace.
495: */
496: private void printStackTraceAsCause(PrintStream s,
497: StackTraceElement[] causedTrace) {
498: // assert Thread.holdsLock(s);
499:
500: // Compute number of frames in common between this and caused
501: StackTraceElement[] trace = getOurStackTrace();
502: int m = trace.length - 1, n = causedTrace.length - 1;
503: while (m >= 0 && n >= 0 && trace[m].equals(causedTrace[n])) {
504: m--;
505: n--;
506: }
507: int framesInCommon = trace.length - 1 - m;
508:
509: s.println("Caused by: " + this );
510: for (int i = 0; i <= m; i++)
511: s.println("\tat " + trace[i]);
512: if (framesInCommon != 0)
513: s.println("\t... " + framesInCommon + " more");
514:
515: // Recurse if we have a cause
516: Throwable ourCause = getCause();
517: if (ourCause != null)
518: ourCause.printStackTraceAsCause(s, trace);
519: }
520:
521: /**
522: * Prints this throwable and its backtrace to the specified
523: * print writer.
524: *
525: * @param s <code>PrintWriter</code> to use for output
526: * @since JDK1.1
527: */
528: public void printStackTrace(PrintWriter s) {
529: synchronized (s) {
530: s.println(this );
531: StackTraceElement[] trace = getOurStackTrace();
532: for (int i = 0; i < trace.length; i++)
533: s.println("\tat " + trace[i]);
534:
535: Throwable ourCause = getCause();
536: if (ourCause != null)
537: ourCause.printStackTraceAsCause(s, trace);
538: }
539: }
540:
541: /**
542: * Print our stack trace as a cause for the specified stack trace.
543: */
544: private void printStackTraceAsCause(PrintWriter s,
545: StackTraceElement[] causedTrace) {
546: // assert Thread.holdsLock(s);
547:
548: // Compute number of frames in common between this and caused
549: StackTraceElement[] trace = getOurStackTrace();
550: int m = trace.length - 1, n = causedTrace.length - 1;
551: while (m >= 0 && n >= 0 && trace[m].equals(causedTrace[n])) {
552: m--;
553: n--;
554: }
555: int framesInCommon = trace.length - 1 - m;
556:
557: s.println("Caused by: " + this );
558: for (int i = 0; i <= m; i++)
559: s.println("\tat " + trace[i]);
560: if (framesInCommon != 0)
561: s.println("\t... " + framesInCommon + " more");
562:
563: // Recurse if we have a cause
564: Throwable ourCause = getCause();
565: if (ourCause != null)
566: ourCause.printStackTraceAsCause(s, trace);
567: }
568:
569: /**
570: * Fills in the execution stack trace. This method records within this
571: * <code>Throwable</code> object information about the current state of
572: * the stack frames for the current thread.
573: *
574: * @return a reference to this <code>Throwable</code> instance.
575: * @see java.lang.Throwable#printStackTrace()
576: */
577: public synchronized native Throwable fillInStackTrace();
578:
579: /**
580: * Provides programmatic access to the stack trace information printed by
581: * {@link #printStackTrace()}. Returns an array of stack trace elements,
582: * each representing one stack frame. The zeroth element of the array
583: * (assuming the array's length is non-zero) represents the top of the
584: * stack, which is the last method invocation in the sequence. Typically,
585: * this is the point at which this throwable was created and thrown.
586: * The last element of the array (assuming the array's length is non-zero)
587: * represents the bottom of the stack, which is the first method invocation
588: * in the sequence.
589: *
590: * <p>Some virtual machines may, under some circumstances, omit one
591: * or more stack frames from the stack trace. In the extreme case,
592: * a virtual machine that has no stack trace information concerning
593: * this throwable is permitted to return a zero-length array from this
594: * method. Generally speaking, the array returned by this method will
595: * contain one element for every frame that would be printed by
596: * <tt>printStackTrace</tt>.
597: *
598: * @return an array of stack trace elements representing the stack trace
599: * pertaining to this throwable.
600: * @since 1.4
601: */
602: public StackTraceElement[] getStackTrace() {
603: return (StackTraceElement[]) getOurStackTrace().clone();
604: }
605:
606: private synchronized StackTraceElement[] getOurStackTrace() {
607: // Initialize stack trace if this is the first call to this method
608: if (stackTrace == null) {
609: int depth = getStackTraceDepth();
610: stackTrace = new StackTraceElement[depth];
611: for (int i = 0; i < depth; i++)
612: stackTrace[i] = getStackTraceElement(i);
613: }
614: return stackTrace;
615: }
616:
617: /**
618: * Sets the stack trace elements that will be returned by
619: * {@link #getStackTrace()} and printed by {@link #printStackTrace()}
620: * and related methods.
621: *
622: * This method, which is designed for use by RPC frameworks and other
623: * advanced systems, allows the client to override the default
624: * stack trace that is either generated by {@link #fillInStackTrace()}
625: * when a throwable is constructed or deserialized when a throwable is
626: * read from a serialization stream.
627: *
628: * @param stackTrace the stack trace elements to be associated with
629: * this <code>Throwable</code>. The specified array is copied by this
630: * call; changes in the specified array after the method invocation
631: * returns will have no affect on this <code>Throwable</code>'s stack
632: * trace.
633: *
634: * @throws NullPointerException if <code>stackTrace</code> is
635: * <code>null</code>, or if any of the elements of
636: * <code>stackTrace</code> are <code>null</code>
637: *
638: * @since 1.4
639: */
640: public void setStackTrace(StackTraceElement[] stackTrace) {
641: StackTraceElement[] defensiveCopy = (StackTraceElement[]) stackTrace
642: .clone();
643: for (int i = 0; i < defensiveCopy.length; i++)
644: if (defensiveCopy[i] == null)
645: throw new NullPointerException("stackTrace[" + i + "]");
646:
647: this .stackTrace = defensiveCopy;
648: }
649:
650: /**
651: * Returns the number of elements in the stack trace (or 0 if the stack
652: * trace is unavailable).
653: */
654: private native int getStackTraceDepth();
655:
656: /**
657: * Returns the specified element of the stack trace.
658: *
659: * @param index index of the element to return.
660: * @throws IndexOutOfBoundsException if <tt>index < 0 ||
661: * index >= getStackTraceDepth() </tt>
662: */
663: private native StackTraceElement getStackTraceElement(int index);
664:
665: private synchronized void writeObject(java.io.ObjectOutputStream s)
666: throws IOException {
667: getOurStackTrace(); // Ensure that stackTrace field is initialized.
668: s.defaultWriteObject();
669: }
670: }
|