From dc7b1dda60ba8c8aa03da26f5555d07074cdce3f Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Fri, 12 Jul 2002 12:52:44 +0000 Subject: natThrowable.cc (printRawStackTrace): removed. * java/lang/natThrowable.cc (printRawStackTrace): removed. (getStackTrace0): new method. * java/lang/Throwable.java (CPlusPlusDemangler): removed. (printStackTrace(PrintWriter)): replace with pure java implementation. (printRawStackTrace): removed. (getStackTrace0): new method. * java/lang/StackTraceElement.java (toString): add extra whitespace. * gcj/javaprims.h: regenerate class list. * include/name-finder.h (lookup): new returns StackTraceElement*. (method_name, file_name): fields removed. (pid2, f2_pipe, b2_pipe, b2_pipe_fd): new fields. (~_Jv_name_finder): close new descriptors. * name-finder.cc(_Jv_name_finder): setup c++filt helper process. (createStackTraceElement): new method. (lookup): returns StackTraceElement*, uses createStackTraceElement(). From-SVN: r55424 --- libjava/java/lang/StackTraceElement.java | 2 +- libjava/java/lang/Throwable.java | 180 ++++++++++++++++--------------- libjava/java/lang/natThrowable.cc | 39 +++---- 3 files changed, 112 insertions(+), 109 deletions(-) (limited to 'libjava/java/lang') diff --git a/libjava/java/lang/StackTraceElement.java b/libjava/java/lang/StackTraceElement.java index 9c60ab1..d9e8a31 100644 --- a/libjava/java/lang/StackTraceElement.java +++ b/libjava/java/lang/StackTraceElement.java @@ -191,7 +191,7 @@ public class StackTraceElement implements Serializable } if (methodName != null) sb.append(methodName); - sb.append('('); + sb.append(" ("); if (fileName != null) sb.append(fileName); else diff --git a/libjava/java/lang/Throwable.java b/libjava/java/lang/Throwable.java index d5488b8..56c9d54 100644 --- a/libjava/java/lang/Throwable.java +++ b/libjava/java/lang/Throwable.java @@ -57,76 +57,6 @@ import java.io.OutputStream; * bytecode not implemented. JDK 1.1. */ -/* A CPlusPlusDemangler sits on top of a PrintWriter. All input is - * passed through the "c++filt" program (part of GNU binutils) which - * demangles internal symbols to their C++ source form. - * - * Closing a CPlusPlusDemangler doesn't close the underlying - * PrintWriter; it does, however close underlying process and flush - * all its buffers, so it's possible to guarantee that after a - * CPlusPlusDemangler has been closed no more will ever be written to - * the underlying PrintWriter. - * - * FIXME: This implictly converts data from the input stream, which is - * a stream of characters, to a stream of bytes. We need a way of - * handling Unicode characters in demangled identifiers. */ - -class CPlusPlusDemangler extends OutputStream -{ - java.io.OutputStream procOut; - java.io.InputStream procIn; - java.lang.Process proc; - PrintWriter p; - - /* The number of bytes written to the underlying PrintWriter. This - provides a crude but fairly portable way to determine whether or - not the attempt to exec c++filt worked. */ - public int written = 0; - - CPlusPlusDemangler (PrintWriter writer) throws IOException - { - p = writer; - proc = Runtime.getRuntime ().exec ("c++filt -s java"); - procOut = proc.getOutputStream (); - procIn = proc.getInputStream (); - } - - public void write (int b) throws IOException - { - procOut.write (b); - while (procIn.available () != 0) - { - int c = procIn.read (); - if (c == -1) - break; - else - { - p.write (c); - written++; - } - } - } - - public void close () throws IOException - { - procOut.close (); - int c; - while ((c = procIn.read ()) != -1) - { - p.write (c); - written++; - } - p.flush (); - try - { - proc.waitFor (); - } - catch (InterruptedException _) - { - } - } -} - /** * Throwable is the superclass of all exceptions that can be raised. * @@ -219,8 +149,7 @@ public class Throwable implements Serializable * no null entries * @since 1.4 */ - // XXX Don't initialize this, once fillInStackTrace() does it. - private StackTraceElement[] stackTrace = {}; + private StackTraceElement[] stackTrace; /** * Instantiate this Throwable with an empty message. The cause remains @@ -449,26 +378,102 @@ public class Throwable implements Serializable } /** - * Print a stack trace to the specified PrintWriter. See - * {@link #printStackTrace()} for the sample format. + *

Prints the exception, the detailed message and the stack trace + * associated with this Throwable to the given PrintWriter. + * The actual output written is implemention specific. Use the result of + * getStackTrace() when more precise information is needed. + * + *

This implementation first prints a line with the result of this + * object's toString() method. + *
+ * Then for all elements given by getStackTrace it prints + * a line containing three spaces, the string "at " and the result of calling + * the toString() method on the StackTraceElement + * object. If getStackTrace() returns an empty array it prints + * a line containing three spaces and the string + * "<<No stacktrace available>>". + *
+ * Then if getCause() doesn't return null it adds a line + * starting with "Caused by: " and the result of calling + * toString() on the cause. + *
+ * Then for every cause (of a cause, etc) the stacktrace is printed the + * same as for the top level Throwable except that as soon + * as all the remaining stack frames of the cause are the same as the + * the last stack frames of the throwable that the cause is wrapped in + * then a line starting with three spaces and the string "... X more" is + * printed, where X is the number of remaining stackframes. * * @param w the PrintWriter to write the trace to * @since 1.1 */ - public void printStackTrace (PrintWriter wr) + public void printStackTrace (PrintWriter pw) { - try + // First line + pw.println(toString()); + + // The stacktrace + StackTraceElement[] stack = getStackTrace(); + if (stack == null || stack.length == 0) { - CPlusPlusDemangler cPlusPlusFilter = new CPlusPlusDemangler (wr); - PrintWriter writer = new PrintWriter (cPlusPlusFilter); - printRawStackTrace (writer); - writer.close (); - if (cPlusPlusFilter.written == 0) // The demangler has failed... - printRawStackTrace (wr); + pw.println(" <>"); + return; } - catch (Exception e1) + else + { + for (int i = 0; i < stack.length; i++) + pw.println(" at " + stack[i]); + } + + // The cause(s) + Throwable cause = getCause(); + while (cause != null) { - printRawStackTrace (wr); + // Cause first line + pw.println("Caused by: " + cause); + + // Cause stacktrace + StackTraceElement[] parentStack = stack; + stack = cause.getStackTrace(); + if (stack == null || stack.length == 0) + { + pw.println(" <>"); + } + else if (parentStack == null || parentStack.length == 0) + { + for (int i = 0; i < stack.length; i++) + pw.println(" at " + stack[i]); + } + else + { + boolean equal = false; // Is rest of stack equal to parent frame? + for (int i = 0; i < stack.length && ! equal; i++) + { + // Check if we already printed the rest of the stack + // since it was the tail of the parent stack + int remaining = stack.length - i; + int element = i; + int parentElement = parentStack.length - remaining; + equal = parentElement >= 0 + && parentElement < parentStack.length; // be optimistic + while (equal && element < stack.length) + { + if (stack[element].equals(parentStack[parentElement])) + { + element++; + parentElement++; + } + else + equal = false; + } + // Print stacktrace element or indicate the rest is equal + if (! equal) + pw.println(" at " + stack[i]); + else + pw.println(" ..." + remaining + " more"); + } + } + cause = cause.getCause(); } } @@ -493,6 +498,9 @@ public class Throwable implements Serializable */ public StackTraceElement[] getStackTrace() { + if (stackTrace == null) + stackTrace = getStackTrace0(); + return stackTrace; } @@ -513,8 +521,8 @@ public class Throwable implements Serializable this.stackTrace = stackTrace; } - private native final void printRawStackTrace (PrintWriter wr); - + private native final StackTraceElement[] getStackTrace0 (); + // Setting this flag to false prevents fillInStackTrace() from running. static boolean trace_enabled = true; private transient byte stackTraceBytes[]; diff --git a/libjava/java/lang/natThrowable.cc b/libjava/java/lang/natThrowable.cc index e644708..c2f7d1b 100644 --- a/libjava/java/lang/natThrowable.cc +++ b/libjava/java/lang/natThrowable.cc @@ -22,6 +22,7 @@ details. */ #include #include #include +#include #include #include #include @@ -67,38 +68,32 @@ java::lang::Throwable::fillInStackTrace (void) return this; } -void -java::lang::Throwable::printRawStackTrace (java::io::PrintWriter *wr) +JArray * +java::lang::Throwable::getStackTrace0 () { - wr->println (toString ()); #ifdef HAVE_BACKTRACE if (!stackTraceBytes) - return; + return NULL; int depth = stackTraceBytes->length / sizeof (void *); void *p[depth]; + // This memcpy is esential; it ensures that the array of void* is + // correctly aligned. memcpy (p, elements (stackTraceBytes), sizeof p); + JArray *result; + java::lang::StackTraceElement** el; + result = reinterpret_cast *> + (JvNewObjectArray (depth, &java::lang::StackTraceElement::class$, NULL)); + el = elements (result); + _Jv_name_finder finder (_Jv_ThisExecutable ()); for (int i = 0; i < depth; i++) - { - bool found = finder.lookup (p[i]); - wr->print (JvNewStringLatin1 (" at ")); - wr->print (JvNewStringLatin1 (finder.hex)); - if (found) - { - wr->print (JvNewStringLatin1 (": ")); - wr->print (JvNewStringLatin1 (finder.method_name)); - if (finder.file_name[0]) - { - wr->print (JvNewStringLatin1 (" (")); - wr->print (JvNewStringLatin1 (finder.file_name)); - wr->print (JvNewStringLatin1 (")")); - } - } - wr->println (); - } + el[i] = finder.lookup (p[i]); + + return result; +#else + return NULL; #endif /* HAVE_BACKTRACE */ - wr->flush (); } -- cgit v1.1