1. /*
  2. * @(#)Throwable.java 1.51 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.lang;
  8. import java.io.*;
  9. /**
  10. * The <code>Throwable</code> class is the superclass of all errors and
  11. * exceptions in the Java language. Only objects that are instances of this
  12. * class (or one of its subclasses) are thrown by the Java Virtual Machine or
  13. * can be thrown by the Java <code>throw</code> statement. Similarly, only
  14. * this class or one of its subclasses can be the argument type in a
  15. * <code>catch</code> clause.
  16. *
  17. * <p>Instances of two subclasses, {@link java.lang.Error} and
  18. * {@link java.lang.Exception}, are conventionally used to indicate
  19. * that exceptional situations have occurred. Typically, these instances
  20. * are freshly created in the context of the exceptional situation so
  21. * as to include relevant information (such as stack trace data).
  22. *
  23. * <p>A throwable contains a snapshot of the execution stack of its thread at
  24. * the time it was created. It can also contain a message string that gives
  25. * more information about the error. Finally, it can contain a <i>cause</i>:
  26. * another throwable that caused this throwable to get thrown. The cause
  27. * facility is new in release 1.4. It is also known as the <i>chained
  28. * exception</i> facility, as the cause can, itself, have a cause, and so on,
  29. * leading to a "chain" of exceptions, each caused by another.
  30. *
  31. * <p>One reason that a throwable may have a cause is that the class that
  32. * throws it is built atop a lower layered abstraction, and an operation on
  33. * the upper layer fails due to a failure in the lower layer. It would be bad
  34. * design to let the throwable thrown by the lower layer propagate outward, as
  35. * it is generally unrelated to the abstraction provided by the upper layer.
  36. * Further, doing so would tie the API of the upper layer to the details of
  37. * its implementation, assuming the lower layer's exception was a checked
  38. * exception. Throwing a "wrapped exception" (i.e., an exception containing a
  39. * cause) allows the upper layer to communicate the details of the failure to
  40. * its caller without incurring either of these shortcomings. It preserves
  41. * the flexibility to change the implementation of the upper layer without
  42. * changing its API (in particular, the set of exceptions thrown by its
  43. * methods).
  44. *
  45. * <p>A second reason that a throwable may have a cause is that the method
  46. * that throws it must conform to a general-purpose interface that does not
  47. * permit the method to throw the cause directly. For example, suppose
  48. * a persistent collection conforms to the {@link java.util.Collection
  49. * Collection} interface, and that its persistence is implemented atop
  50. * <tt>java.io</tt>. Suppose the internals of the <tt>put</tt> method
  51. * can throw an {@link java.io.IOException IOException}. The implementation
  52. * can communicate the details of the <tt>IOException</tt> to its caller
  53. * while conforming to the <tt>Collection</tt> interface by wrapping the
  54. * <tt>IOException</tt> in an appropriate unchecked exception. (The
  55. * specification for the persistent collection should indicate that it is
  56. * capable of throwing such exceptions.)
  57. *
  58. * <p>A cause can be associated with a throwable in two ways: via a
  59. * constructor that takes the cause as an argument, or via the
  60. * {@link #initCause(Throwable)} method. New throwable classes that
  61. * wish to allow causes to be associated with them should provide constructors
  62. * that take a cause and delegate (perhaps indirectly) to one of the
  63. * <tt>Throwable</tt> constructors that takes a cause. For example:
  64. * <pre>
  65. * try {
  66. * lowLevelOp();
  67. * } catch (LowLevelException le) {
  68. * throw new HighLevelException(le); // Chaining-aware constructor
  69. * }
  70. * </pre>
  71. * Because the <tt>initCause</tt> method is public, it allows a cause to be
  72. * associated with any throwable, even a "legacy throwable" whose
  73. * implementation predates the addition of the exception chaining mechanism to
  74. * <tt>Throwable</tt>. For example:
  75. * <pre>
  76. * try {
  77. * lowLevelOp();
  78. * } catch (LowLevelException le) {
  79. * throw (HighLevelException)
  80. new HighLevelException().initCause(le); // Legacy constructor
  81. * }
  82. * </pre>
  83. *
  84. * <p>Prior to release 1.4, there were many throwables that had their own
  85. * non-standard exception chaining mechanisms (
  86. * {@link ExceptionInInitializerError}, {@link ClassNotFoundException},
  87. * {@link java.lang.reflect.UndeclaredThrowableException},
  88. * {@link java.lang.reflect.InvocationTargetException},
  89. * {@link java.io.WriteAbortedException},
  90. * {@link java.security.PrivilegedActionException},
  91. * {@link java.awt.print.PrinterIOException} and
  92. * {@link java.rmi.RemoteException}).
  93. * As of release 1.4, all of these throwables have been retrofitted to
  94. * use the standard exception chaining mechanism, while continuing to
  95. * implement their "legacy" chaining mechanisms for compatibility.
  96. *
  97. * <p>Further, as of release 1.4, many general purpose <tt>Throwable</tt>
  98. * classes (for example {@link Exception}, {@link RuntimeException},
  99. * {@link Error}) have been retrofitted with constructors that take
  100. * a cause. This was not strictly necessary, due to the existence of the
  101. * <tt>initCause</tt> method, but it is more convenient and expressive to
  102. * delegate to a constructor that takes a cause.
  103. *
  104. * <p>By convention, class <code>Throwable</code> and its subclasses have two
  105. * constructors, one that takes no arguments and one that takes a
  106. * <code>String</code> argument that can be used to produce a detail message.
  107. * Further, those subclasses that might likely have a cause associated with
  108. * them should have two more constructors, one that takes a
  109. * <code>Throwable</code> (the cause), and one that takes a
  110. * <code>String</code> (the detail message) and a <code>Throwable</code> (the
  111. * cause).
  112. *
  113. * <p>Also introduced in release 1.4 is the {@link #getStackTrace()} method,
  114. * which allows programmatic access to the stack trace information that was
  115. * previously available only in text form, via the various forms of the
  116. * {@link #printStackTrace()} method. This information has been added to the
  117. * <i>serialized representation</i> of this class so <tt>getStackTrace</tt>
  118. * and <tt>printStackTrace</tt> will operate properly on a throwable that
  119. * was obtained by deserialization.
  120. *
  121. * @author unascribed
  122. * @author Josh Bloch (Added exception chaining and programmatic access to
  123. * stack trace in 1.4.)
  124. * @version 1.51, 01/23/03
  125. * @since JDK1.0
  126. */
  127. public class Throwable implements Serializable {
  128. /** use serialVersionUID from JDK 1.0.2 for interoperability */
  129. private static final long serialVersionUID = -3042686055658047285L;
  130. /**
  131. * Native code saves some indication of the stack backtrace in this slot.
  132. */
  133. private transient Object backtrace;
  134. /**
  135. * Specific details about the Throwable. For example, for
  136. * <tt>FileNotFoundException</tt>, this contains the name of
  137. * the file that could not be found.
  138. *
  139. * @serial
  140. */
  141. private String detailMessage;
  142. /**
  143. * The throwable that caused this throwable to get thrown, or null if this
  144. * throwable was not caused by another throwable, or if the causative
  145. * throwable is unknown. If this field is equal to this throwable itself,
  146. * it indicates that the cause of this throwable has not yet been
  147. * initialized.
  148. *
  149. * @serial
  150. * @since 1.4
  151. */
  152. private Throwable cause = this;
  153. /**
  154. * The stack trace, as returned by {@link #getStackTrace()}.
  155. *
  156. * @serial
  157. * @since 1.4
  158. */
  159. private StackTraceElement[] stackTrace;
  160. /*
  161. * This field is lazily initialized on first use or serialization and
  162. * nulled out when fillInStackTrace is called.
  163. */
  164. /**
  165. * Constructs a new throwable with <code>null</code> as its detail message.
  166. * The cause is not initialized, and may subsequently be initialized by a
  167. * call to {@link #initCause}.
  168. *
  169. * <p>The {@link #fillInStackTrace()} method is called to initialize
  170. * the stack trace data in the newly created throwable.
  171. */
  172. public Throwable() {
  173. fillInStackTrace();
  174. }
  175. /**
  176. * Constructs a new throwable with the specified detail message. The
  177. * cause is not initialized, and may subsequently be initialized by
  178. * a call to {@link #initCause}.
  179. *
  180. * <p>The {@link #fillInStackTrace()} method is called to initialize
  181. * the stack trace data in the newly created throwable.
  182. *
  183. * @param message the detail message. The detail message is saved for
  184. * later retrieval by the {@link #getMessage()} method.
  185. */
  186. public Throwable(String message) {
  187. fillInStackTrace();
  188. detailMessage = message;
  189. }
  190. /**
  191. * Constructs a new throwable with the specified detail message and
  192. * cause. <p>Note that the detail message associated with
  193. * <code>cause</code> is <i>not</i> automatically incorporated in
  194. * this throwable's detail message.
  195. *
  196. * <p>The {@link #fillInStackTrace()} method is called to initialize
  197. * the stack trace data in the newly created throwable.
  198. *
  199. * @param message the detail message (which is saved for later retrieval
  200. * by the {@link #getMessage()} method).
  201. * @param cause the cause (which is saved for later retrieval by the
  202. * {@link #getCause()} method). (A <tt>null</tt> value is
  203. * permitted, and indicates that the cause is nonexistent or
  204. * unknown.)
  205. * @since 1.4
  206. */
  207. public Throwable(String message, Throwable cause) {
  208. fillInStackTrace();
  209. detailMessage = message;
  210. this.cause = cause;
  211. }
  212. /**
  213. * Constructs a new throwable with the specified cause and a detail
  214. * message of <tt>(cause==null ? null : cause.toString())</tt> (which
  215. * typically contains the class and detail message of <tt>cause</tt>).
  216. * This constructor is useful for throwables that are little more than
  217. * wrappers for other throwables (for example, {@link
  218. * java.security.PrivilegedActionException}).
  219. *
  220. * <p>The {@link #fillInStackTrace()} method is called to initialize
  221. * the stack trace data in the newly created throwable.
  222. *
  223. * @param cause the cause (which is saved for later retrieval by the
  224. * {@link #getCause()} method). (A <tt>null</tt> value is
  225. * permitted, and indicates that the cause is nonexistent or
  226. * unknown.)
  227. * @since 1.4
  228. */
  229. public Throwable(Throwable cause) {
  230. fillInStackTrace();
  231. detailMessage = (cause==null ? null : cause.toString());
  232. this.cause = cause;
  233. }
  234. /**
  235. * Returns the detail message string of this throwable.
  236. *
  237. * @return the detail message string of this <tt>Throwable</tt> instance
  238. * (which may be <tt>null</tt>).
  239. */
  240. public String getMessage() {
  241. return detailMessage;
  242. }
  243. /**
  244. * Creates a localized description of this throwable.
  245. * Subclasses may override this method in order to produce a
  246. * locale-specific message. For subclasses that do not override this
  247. * method, the default implementation returns the same result as
  248. * <code>getMessage()</code>.
  249. *
  250. * @return The localized description of this throwable.
  251. * @since JDK1.1
  252. */
  253. public String getLocalizedMessage() {
  254. return getMessage();
  255. }
  256. /**
  257. * Returns the cause of this throwable or <code>null</code> if the
  258. * cause is nonexistent or unknown. (The cause is the throwable that
  259. * caused this throwable to get thrown.)
  260. *
  261. * <p>This implementation returns the cause that was supplied via one of
  262. * the constructors requiring a <tt>Throwable</tt>, or that was set after
  263. * creation with the {@link #initCause(Throwable)} method. While it is
  264. * typically unnecessary to override this method, a subclass can override
  265. * it to return a cause set by some other means. This is appropriate for
  266. * a "legacy chained throwable" that predates the addition of chained
  267. * exceptions to <tt>Throwable</tt>. Note that it is <i>not</i>
  268. * necessary to override any of the <tt>PrintStackTrace</tt> methods,
  269. * all of which invoke the <tt>getCause</tt> method to determine the
  270. * cause of a throwable.
  271. *
  272. * @return the cause of this throwable or <code>null</code> if the
  273. * cause is nonexistent or unknown.
  274. * @since 1.4
  275. */
  276. public Throwable getCause() {
  277. return (cause==this ? null : cause);
  278. }
  279. /**
  280. * Initializes the <i>cause</i> of this throwable to the specified value.
  281. * (The cause is the throwable that caused this throwable to get thrown.)
  282. *
  283. * <p>This method can be called at most once. It is generally called from
  284. * within the constructor, or immediately after creating the
  285. * throwable. If this throwable was created
  286. * with {@link #Throwable(Throwable)} or
  287. * {@link #Throwable(String,Throwable)}, this method cannot be called
  288. * even once.
  289. *
  290. * @param cause the cause (which is saved for later retrieval by the
  291. * {@link #getCause()} method). (A <tt>null</tt> value is
  292. * permitted, and indicates that the cause is nonexistent or
  293. * unknown.)
  294. * @return a reference to this <code>Throwable</code> instance.
  295. * @throws IllegalArgumentException if <code>cause</code> is this
  296. * throwable. (A throwable cannot be its own cause.)
  297. * @throws IllegalStateException if this throwable was
  298. * created with {@link #Throwable(Throwable)} or
  299. * {@link #Throwable(String,Throwable)}, or this method has already
  300. * been called on this throwable.
  301. * @since 1.4
  302. */
  303. public synchronized Throwable initCause(Throwable cause) {
  304. if (this.cause != this)
  305. throw new IllegalStateException("Can't overwrite cause");
  306. if (cause == this)
  307. throw new IllegalArgumentException("Self-causation not permitted");
  308. this.cause = cause;
  309. return this;
  310. }
  311. /**
  312. * Returns a short description of this throwable.
  313. * If this <code>Throwable</code> object was created with a non-null detail
  314. * message string, then the result is the concatenation of three strings:
  315. * <ul>
  316. * <li>The name of the actual class of this object
  317. * <li>": " (a colon and a space)
  318. * <li>The result of the {@link #getMessage} method for this object
  319. * </ul>
  320. * If this <code>Throwable</code> object was created with a <tt>null</tt>
  321. * detail message string, then the name of the actual class of this object
  322. * is returned.
  323. *
  324. * @return a string representation of this throwable.
  325. */
  326. public String toString() {
  327. String s = getClass().getName();
  328. String message = getLocalizedMessage();
  329. return (message != null) ? (s + ": " + message) : s;
  330. }
  331. /**
  332. * Prints this throwable and its backtrace to the
  333. * standard error stream. This method prints a stack trace for this
  334. * <code>Throwable</code> object on the error output stream that is
  335. * the value of the field <code>System.err</code>. The first line of
  336. * output contains the result of the {@link #toString()} method for
  337. * this object. Remaining lines represent data previously recorded by
  338. * the method {@link #fillInStackTrace()}. The format of this
  339. * information depends on the implementation, but the following
  340. * example may be regarded as typical:
  341. * <blockquote><pre>
  342. * java.lang.NullPointerException
  343. * at MyClass.mash(MyClass.java:9)
  344. * at MyClass.crunch(MyClass.java:6)
  345. * at MyClass.main(MyClass.java:3)
  346. * </pre></blockquote>
  347. * This example was produced by running the program:
  348. * <pre>
  349. * class MyClass {
  350. * public static void main(String[] args) {
  351. * crunch(null);
  352. * }
  353. * static void crunch(int[] a) {
  354. * mash(a);
  355. * }
  356. * static void mash(int[] b) {
  357. * System.out.println(b[0]);
  358. * }
  359. * }
  360. * </pre>
  361. * The backtrace for a throwable with an initialized, non-null cause
  362. * should generally include the backtrace for the cause. The format
  363. * of this information depends on the implementation, but the following
  364. * example may be regarded as typical:
  365. * <pre>
  366. * HighLevelException: MidLevelException: LowLevelException
  367. * at Junk.a(Junk.java:13)
  368. * at Junk.main(Junk.java:4)
  369. * Caused by: MidLevelException: LowLevelException
  370. * at Junk.c(Junk.java:23)
  371. * at Junk.b(Junk.java:17)
  372. * at Junk.a(Junk.java:11)
  373. * ... 1 more
  374. * Caused by: LowLevelException
  375. * at Junk.e(Junk.java:30)
  376. * at Junk.d(Junk.java:27)
  377. * at Junk.c(Junk.java:21)
  378. * ... 3 more
  379. * </pre>
  380. * Note the presence of lines containing the characters <tt>"..."</tt>.
  381. * These lines indicate that the remainder of the stack trace for this
  382. * exception matches the indicated number of frames from the bottom of the
  383. * stack trace of the exception that was caused by this exception (the
  384. * "enclosing" exception). This shorthand can greatly reduce the length
  385. * of the output in the common case where a wrapped exception is thrown
  386. * from same method as the "causative exception" is caught. The above
  387. * example was produced by running the program:
  388. * <pre>
  389. * public class Junk {
  390. * public static void main(String args[]) {
  391. * try {
  392. * a();
  393. * } catch(HighLevelException e) {
  394. * e.printStackTrace();
  395. * }
  396. * }
  397. * static void a() throws HighLevelException {
  398. * try {
  399. * b();
  400. * } catch(MidLevelException e) {
  401. * throw new HighLevelException(e);
  402. * }
  403. * }
  404. * static void b() throws MidLevelException {
  405. * c();
  406. * }
  407. * static void c() throws MidLevelException {
  408. * try {
  409. * d();
  410. * } catch(LowLevelException e) {
  411. * throw new MidLevelException(e);
  412. * }
  413. * }
  414. * static void d() throws LowLevelException {
  415. * e();
  416. * }
  417. * static void e() throws LowLevelException {
  418. * throw new LowLevelException();
  419. * }
  420. * }
  421. *
  422. * class HighLevelException extends Exception {
  423. * HighLevelException(Throwable cause) { super(cause); }
  424. * }
  425. *
  426. * class MidLevelException extends Exception {
  427. * MidLevelException(Throwable cause) { super(cause); }
  428. * }
  429. *
  430. * class LowLevelException extends Exception {
  431. * }
  432. * </pre>
  433. */
  434. public void printStackTrace() {
  435. printStackTrace(System.err);
  436. }
  437. /**
  438. * Prints this throwable and its backtrace to the specified print stream.
  439. *
  440. * @param s <code>PrintStream</code> to use for output
  441. */
  442. public void printStackTrace(PrintStream s) {
  443. synchronized (s) {
  444. s.println(this);
  445. StackTraceElement[] trace = getOurStackTrace();
  446. for (int i=0; i < trace.length; i++)
  447. s.println("\tat " + trace[i]);
  448. Throwable ourCause = getCause();
  449. if (ourCause != null)
  450. ourCause.printStackTraceAsCause(s, trace);
  451. }
  452. }
  453. /**
  454. * Print our stack trace as a cause for the specified stack trace.
  455. */
  456. private void printStackTraceAsCause(PrintStream s,
  457. StackTraceElement[] causedTrace)
  458. {
  459. // assert Thread.holdsLock(s);
  460. // Compute number of frames in common between this and caused
  461. StackTraceElement[] trace = getOurStackTrace();
  462. int m = trace.length-1, n = causedTrace.length-1;
  463. while (m >= 0 && n >=0 && trace[m].equals(causedTrace[n])) {
  464. m--; n--;
  465. }
  466. int framesInCommon = trace.length - 1 - m;
  467. s.println("Caused by: " + this);
  468. for (int i=0; i <= m; i++)
  469. s.println("\tat " + trace[i]);
  470. if (framesInCommon != 0)
  471. s.println("\t... " + framesInCommon + " more");
  472. // Recurse if we have a cause
  473. Throwable ourCause = getCause();
  474. if (ourCause != null)
  475. ourCause.printStackTraceAsCause(s, trace);
  476. }
  477. /**
  478. * Prints this throwable and its backtrace to the specified
  479. * print writer.
  480. *
  481. * @param s <code>PrintWriter</code> to use for output
  482. * @since JDK1.1
  483. */
  484. public void printStackTrace(PrintWriter s) {
  485. synchronized (s) {
  486. s.println(this);
  487. StackTraceElement[] trace = getOurStackTrace();
  488. for (int i=0; i < trace.length; i++)
  489. s.println("\tat " + trace[i]);
  490. Throwable ourCause = getCause();
  491. if (ourCause != null)
  492. ourCause.printStackTraceAsCause(s, trace);
  493. }
  494. }
  495. /**
  496. * Print our stack trace as a cause for the specified stack trace.
  497. */
  498. private void printStackTraceAsCause(PrintWriter s,
  499. StackTraceElement[] causedTrace)
  500. {
  501. // assert Thread.holdsLock(s);
  502. // Compute number of frames in common between this and caused
  503. StackTraceElement[] trace = getOurStackTrace();
  504. int m = trace.length-1, n = causedTrace.length-1;
  505. while (m >= 0 && n >=0 && trace[m].equals(causedTrace[n])) {
  506. m--; n--;
  507. }
  508. int framesInCommon = trace.length - 1 - m;
  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. // Recurse if we have a cause
  515. Throwable ourCause = getCause();
  516. if (ourCause != null)
  517. ourCause.printStackTraceAsCause(s, trace);
  518. }
  519. /**
  520. * Fills in the execution stack trace. This method records within this
  521. * <code>Throwable</code> object information about the current state of
  522. * the stack frames for the current thread.
  523. *
  524. * @return a reference to this <code>Throwable</code> instance.
  525. * @see java.lang.Throwable#printStackTrace()
  526. */
  527. public synchronized native Throwable fillInStackTrace();
  528. /**
  529. * Provides programmatic access to the stack trace information printed by
  530. * {@link #printStackTrace()}. Returns an array of stack trace elements,
  531. * each representing one stack frame. The zeroth element of the array
  532. * (assuming the array's length is non-zero) represents the top of the
  533. * stack, which is the last method invocation in the sequence. Typically,
  534. * this is the point at which this throwable was created and thrown.
  535. * The last element of the array (assuming the array's length is non-zero)
  536. * represents the bottom of the stack, which is the first method invocation
  537. * in the sequence.
  538. *
  539. * <p>Some virtual machines may, under some circumstances, omit one
  540. * or more stack frames from the stack trace. In the extreme case,
  541. * a virtual machine that has no stack trace information concerning
  542. * this throwable is permitted to return a zero-length array from this
  543. * method. Generally speaking, the array returned by this method will
  544. * contain one element for every frame that would be printed by
  545. * <tt>printStackTrace</tt>.
  546. *
  547. * @return an array of stack trace elements representing the stack trace
  548. * pertaining to this throwable.
  549. * @since 1.4
  550. */
  551. public StackTraceElement[] getStackTrace() {
  552. return (StackTraceElement[]) getOurStackTrace().clone();
  553. }
  554. private synchronized StackTraceElement[] getOurStackTrace() {
  555. // Initialize stack trace if this is the first call to this method
  556. if (stackTrace == null) {
  557. int depth = getStackTraceDepth();
  558. stackTrace = new StackTraceElement[depth];
  559. for (int i=0; i < depth; i++)
  560. stackTrace[i] = getStackTraceElement(i);
  561. }
  562. return stackTrace;
  563. }
  564. /**
  565. * Sets the stack trace elements that will be returned by
  566. * {@link #getStackTrace()} and printed by {@link #printStackTrace()}
  567. * and related methods.
  568. *
  569. * This method, which is designed for use by RPC frameworks and other
  570. * advanced systems, allows the client to override the default
  571. * stack trace that is either generated by {@link #fillInStackTrace()}
  572. * when a throwable is constructed or deserialized when a throwable is
  573. * read from a serialization stream.
  574. *
  575. * @param stackTrace the stack trace elements to be associated with
  576. * this <code>Throwable</code>. The specified array is copied by this
  577. * call; changes in the specified array after the method invocation
  578. * returns will have no affect on this <code>Throwable</code>'s stack
  579. * trace.
  580. *
  581. * @throws NullPointerException if <code>stackTrace</code> is
  582. * <code>null</code>, or if any of the elements of
  583. * <code>stackTrace</code> are <code>null</code>
  584. *
  585. * @since 1.4
  586. */
  587. public void setStackTrace(StackTraceElement[] stackTrace) {
  588. StackTraceElement[] defensiveCopy =
  589. (StackTraceElement[]) stackTrace.clone();
  590. for (int i = 0; i < defensiveCopy.length; i++)
  591. if (defensiveCopy[i] == null)
  592. throw new NullPointerException("stackTrace[" + i + "]");
  593. this.stackTrace = defensiveCopy;
  594. }
  595. /**
  596. * Returns the number of elements in the stack trace (or 0 if the stack
  597. * trace is unavailable).
  598. */
  599. private native int getStackTraceDepth();
  600. /**
  601. * Returns the specified element of the stack trace.
  602. *
  603. * @param index index of the element to return.
  604. * @throws IndexOutOfBoundsException if <tt>index %lt; 0 ||
  605. * index >= getStackTraceDepth() </tt>
  606. */
  607. private native StackTraceElement getStackTraceElement(int index);
  608. private synchronized void writeObject(java.io.ObjectOutputStream s)
  609. throws IOException
  610. {
  611. getOurStackTrace(); // Ensure that stackTrace field is initialized.
  612. s.defaultWriteObject();
  613. }
  614. }