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
This commit is contained in:
Mark Wielaard 2002-07-12 12:52:44 +00:00 committed by Mark Wielaard
parent 26af4041b7
commit dc7b1dda60
7 changed files with 337 additions and 159 deletions

View file

@ -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

View file

@ -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.
* <p>Prints the exception, the detailed message and the stack trace
* associated with this Throwable to the given <code>PrintWriter</code>.
* The actual output written is implemention specific. Use the result of
* <code>getStackTrace()</code> when more precise information is needed.
*
* <p>This implementation first prints a line with the result of this
* object's <code>toString()</code> method.
* <br>
* Then for all elements given by <code>getStackTrace</code> it prints
* a line containing three spaces, the string "at " and the result of calling
* the <code>toString()</code> method on the <code>StackTraceElement</code>
* object. If <code>getStackTrace()</code> returns an empty array it prints
* a line containing three spaces and the string
* "&lt;&lt;No stacktrace available&gt;&gt;".
* <br>
* Then if <code>getCause()</code> doesn't return null it adds a line
* starting with "Caused by: " and the result of calling
* <code>toString()</code> on the cause.
* <br>
* Then for every cause (of a cause, etc) the stacktrace is printed the
* same as for the top level <code>Throwable</code> 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(" <<No stacktrace available>>");
return;
}
catch (Exception e1)
else
{
printRawStackTrace (wr);
for (int i = 0; i < stack.length; i++)
pw.println(" at " + stack[i]);
}
// The cause(s)
Throwable cause = getCause();
while (cause != null)
{
// Cause first line
pw.println("Caused by: " + cause);
// Cause stacktrace
StackTraceElement[] parentStack = stack;
stack = cause.getStackTrace();
if (stack == null || stack.length == 0)
{
pw.println(" <<No stacktrace available>>");
}
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[];

View file

@ -22,6 +22,7 @@ details. */
#include <java/lang/Object.h>
#include <java-threads.h>
#include <java/lang/Throwable.h>
#include <java/lang/StackTraceElement.h>
#include <java/io/PrintStream.h>
#include <java/io/PrintWriter.h>
#include <java/io/IOException.h>
@ -67,38 +68,32 @@ java::lang::Throwable::fillInStackTrace (void)
return this;
}
void
java::lang::Throwable::printRawStackTrace (java::io::PrintWriter *wr)
JArray<java::lang::StackTraceElement*> *
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<java::lang::StackTraceElement*> *result;
java::lang::StackTraceElement** el;
result = reinterpret_cast <JArray<java::lang::StackTraceElement *>*>
(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 ();
}