aboutsummaryrefslogtreecommitdiff
path: root/libjava/java/lang
diff options
context:
space:
mode:
authorMark Wielaard <mark@klomp.org>2002-08-24 22:46:19 +0000
committerMark Wielaard <mark@gcc.gnu.org>2002-08-24 22:46:19 +0000
commit6e0532cdf6f9fb4776bfa0f05a29c06a362d466b (patch)
tree2194f5746d8d192d6202800f3df90a8ccb1675e0 /libjava/java/lang
parent4906d5d83e08494b70297808d6818faffd89c2a0 (diff)
downloadgcc-6e0532cdf6f9fb4776bfa0f05a29c06a362d466b.zip
gcc-6e0532cdf6f9fb4776bfa0f05a29c06a362d466b.tar.gz
gcc-6e0532cdf6f9fb4776bfa0f05a29c06a362d466b.tar.bz2
Makefile.am (libgcj_la_SOURCES): Remove name-finder.cc.
* Makefile.am (libgcj_la_SOURCES): Remove name-finder.cc. (core_java_source_files): Add VMThrowable.java and NameFinder.java (nat_source_files): Remove natThrowable.cc, add natVMThrowable.cc and natNameFinder.cc. * Makefile.in: Regenerate. * prims.cc: Use trace_enabled from VMThrowable. * name-finder.cc: Removed. * gcj/javaprims.h: Add class VMThrowable. * gnu/gcj/runtime/NameFinder.java: New file. * gnu/gcj/runtime/natNameFinder.cc: Likewise. * include/name-finder.h: Removed. * java/lang/Throwable.java (printStackTrace (PrintStream)): Use new method stackTraceString(). (printStackTrace (PrintWriter)): Likewise. (stackTraceString): Complete rewrite of old printStackTrace using StringBuffer. (stackTraceStringBuffer): New helper method for stackTraceString(). (fillInStackTrace): Delegate to VMTrowable. (getStackTrace): Likewise. (getStackTrace0): Removed. (trace_enabled, stackTraceBytes): Moved to new VMThrowable.java. (setStackTrace): Copy given array. * java/lang/natThrowable.cc: Removed (replaced by natVMThrowable). * java/lang/VMThrowable.java: New class. * java/lang/natVMThrowable.cc: New file. From-SVN: r56556
Diffstat (limited to 'libjava/java/lang')
-rw-r--r--libjava/java/lang/Throwable.java160
-rw-r--r--libjava/java/lang/VMThrowable.java97
-rw-r--r--libjava/java/lang/natThrowable.cc99
-rw-r--r--libjava/java/lang/natVMThrowable.cc73
4 files changed, 267 insertions, 162 deletions
diff --git a/libjava/java/lang/Throwable.java b/libjava/java/lang/Throwable.java
index 56c9d54..613f43f 100644
--- a/libjava/java/lang/Throwable.java
+++ b/libjava/java/lang/Throwable.java
@@ -46,11 +46,6 @@ import java.io.ObjectInputStream;
import java.io.IOException;
import java.io.OutputStream;
-/**
- * @author Tom Tromey <tromey@cygnus.com>
- * @date October 30, 1998
- */
-
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: Sufficient for compiled code, but methods applicable to
@@ -116,7 +111,7 @@ import java.io.OutputStream;
* @author Tom Tromey
* @author Eric Blake <ebb9@email.byu.edu>
* @since 1.0
- * @status still missing 1.4 functionality
+ * @status updated to 1.4
*/
public class Throwable implements Serializable
{
@@ -130,7 +125,7 @@ public class Throwable implements Serializable
*
* @serial specific details about the exception, may be null
*/
- private String detailMessage;
+ private final String detailMessage;
/**
* The cause of the throwable, including null for an unknown or non-chained
@@ -374,7 +369,7 @@ public class Throwable implements Serializable
*/
public void printStackTrace(PrintStream s)
{
- printStackTrace(new PrintWriter(s));
+ s.print(stackTraceString());
}
/**
@@ -409,72 +404,88 @@ public class Throwable implements Serializable
*/
public void printStackTrace (PrintWriter pw)
{
- // First line
- pw.println(toString());
+ pw.print(stackTraceString());
+ }
- // The stacktrace
+ private static final String nl = System.getProperty("line.separator");
+ // Create whole stack trace in a stringbuffer so we don't have to print
+ // it line by line. This prevents printing multiple stack traces from
+ // different threads to get mixed up when written to the same PrintWriter.
+ private String stackTraceString()
+ {
+ StringBuffer sb = new StringBuffer();
+
+ // Main stacktrace
StackTraceElement[] stack = getStackTrace();
- if (stack == null || stack.length == 0)
- {
- pw.println(" <<No stacktrace available>>");
- return;
- }
- else
- {
- for (int i = 0; i < stack.length; i++)
- pw.println(" at " + stack[i]);
- }
+ stackTraceStringBuffer(sb, this.toString(), stack, 0);
// The cause(s)
Throwable cause = getCause();
while (cause != null)
{
- // Cause first line
- pw.println("Caused by: " + cause);
+ // Cause start first line
+ sb.append("Caused by: ");
// 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]);
- }
+ if (parentStack == null || parentStack.length == 0)
+ stackTraceStringBuffer(sb, cause.toString(), stack, 0);
else
{
- boolean equal = false; // Is rest of stack equal to parent frame?
- for (int i = 0; i < stack.length && ! equal; i++)
+ int equal = 0; // Count how many of the last stack frames are equal
+ int frame = stack.length-1;
+ int parentFrame = parentStack.length-1;
+ while (frame > 0 && parentFrame > 0)
{
- // 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[frame].equals(parentStack[parentFrame]))
{
- if (stack[element].equals(parentStack[parentElement]))
- {
- element++;
- parentElement++;
- }
- else
- equal = false;
+ equal++;
+ frame--;
+ parentFrame--;
}
- // Print stacktrace element or indicate the rest is equal
- if (! equal)
- pw.println(" at " + stack[i]);
else
- pw.println(" ..." + remaining + " more");
+ break;
}
+ stackTraceStringBuffer(sb, cause.toString(), stack, equal);
}
cause = cause.getCause();
}
+
+ return sb.toString();
+ }
+
+ // Adds to the given StringBuffer a line containing the name and
+ // all stacktrace elements minus the last equal ones.
+ private static void stackTraceStringBuffer(StringBuffer sb, String name,
+ StackTraceElement[] stack, int equal)
+ {
+ // (finish) first line
+ sb.append(name);
+ sb.append(nl);
+
+ // The stacktrace
+ if (stack == null || stack.length == 0)
+ {
+ sb.append(" <<No stacktrace available>>");
+ sb.append(nl);
+ }
+ else
+ {
+ for (int i = 0; i < stack.length-equal; i++)
+ {
+ sb.append(" at ");
+ sb.append(stack[i] == null ? "<<Unknown>>" : stack[i].toString());
+ sb.append(nl);
+ }
+ if (equal > 0)
+ {
+ sb.append(" ...");
+ sb.append(equal);
+ sb.append(" more");
+ sb.append(nl);
+ }
+ }
}
/**
@@ -483,7 +494,13 @@ public class Throwable implements Serializable
* @return this same throwable
* @see #printStackTrace()
*/
- public native Throwable fillInStackTrace();
+ public Throwable fillInStackTrace()
+ {
+ vmState = VMThrowable.fillInStackTrace(this);
+ stackTrace = null; // Should be regenerated when used.
+
+ return this;
+ }
/**
* Provides access to the information printed in {@link #printStackTrace()}.
@@ -499,7 +516,13 @@ public class Throwable implements Serializable
public StackTraceElement[] getStackTrace()
{
if (stackTrace == null)
- stackTrace = getStackTrace0();
+ if (vmState == null)
+ stackTrace = new StackTraceElement[0];
+ else
+ {
+ stackTrace = vmState.getStackTrace(this);
+ vmState = null; // No longer needed
+ }
return stackTrace;
}
@@ -508,6 +531,10 @@ public class Throwable implements Serializable
* Change the stack trace manually. This method is designed for remote
* procedure calls, which intend to alter the stack trace before or after
* serialization according to the context of the remote call.
+ * <p>
+ * The contents of the given stacktrace is copied so changes to the
+ * original * array do not change the stack trace elements of this
+ * throwable.
*
* @param stackTrace the new trace to use
* @throws NullPointerException if stackTrace is null or has null elements
@@ -515,15 +542,22 @@ public class Throwable implements Serializable
*/
public void setStackTrace(StackTraceElement[] stackTrace)
{
- for (int i = stackTrace.length; --i >= 0; )
+ int i = stackTrace.length;
+ StackTraceElement[] st = new StackTraceElement[i];
+
+ while (--i >= 0)
if (stackTrace[i] == null)
- throw new NullPointerException();
- this.stackTrace = stackTrace;
- }
+ throw new NullPointerException();
+ else
+ st[i] = stackTrace[i];
- private native final StackTraceElement[] getStackTrace0 ();
+ this.stackTrace = st;
+ }
- // Setting this flag to false prevents fillInStackTrace() from running.
- static boolean trace_enabled = true;
- private transient byte stackTraceBytes[];
+ /**
+ * VM state when fillInStackTrace was called.
+ * Used by getStackTrace() to get an array of StackTraceElements.
+ * Cleared when no longer needed.
+ */
+ private transient VMThrowable vmState;
}
diff --git a/libjava/java/lang/VMThrowable.java b/libjava/java/lang/VMThrowable.java
new file mode 100644
index 0000000..0a2c922
--- /dev/null
+++ b/libjava/java/lang/VMThrowable.java
@@ -0,0 +1,97 @@
+/* java.lang.VMThrowable -- VM support methods for Throwable.
+ Copyright (C) 1998, 1999, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang;
+
+import gnu.gcj.runtime.NameFinder;
+
+/**
+ * VM dependant state and support methods Throwabele.
+ * It is deliberately package local and final and should only be accessed
+ * by the Throwable class.
+ * <p>
+ * This is the version used by libgcj (http://gcc.gnu.org/java/).
+ *
+ * @author Mark Wielaard (mark@klomp.org)
+ */
+final class VMThrowable
+{
+ private gnu.gcj.RawData stackTraceAddrs;
+ private int length;
+
+ /**
+ * Private contructor, create VMThrowables with fillInStackTrace();
+ */
+ private VMThrowable() { }
+
+ /**
+ * Fill in the stack trace with the current execution stack.
+ * Called by <code>Throwable.fillInStackTrace()</code> to get the state of
+ * the VM. Can return null when the VM does not support caputing the VM
+ * execution state.
+ *
+ * @return a new VMThrowable containing the current execution stack trace.
+ * @see Throwable#fillInStackTrace()
+ */
+ static native VMThrowable fillInStackTrace(Throwable t);
+
+ /**
+ * Returns an <code>StackTraceElement</code> array based on the execution
+ * state of the VM as captured by <code>fillInStackTrace</code>.
+ * Called by <code>Throwable.getStackTrace()</code>.
+ *
+ * @return a non-null but possible zero length array of StackTraceElement.
+ * @see Throwable#getStackTrace()
+ */
+ StackTraceElement[] getStackTrace(Throwable t)
+ {
+ StackTraceElement[] result;
+ if (stackTraceAddrs != null)
+ {
+ NameFinder nameFinder = new NameFinder();
+ result = nameFinder.lookup(t, stackTraceAddrs, length);
+ nameFinder.close();
+ }
+ else
+ result = new StackTraceElement[0];
+
+ return result;
+ }
+
+ // Setting this flag to false prevents fillInStackTrace() from running.
+ static boolean trace_enabled = true;
+}
diff --git a/libjava/java/lang/natThrowable.cc b/libjava/java/lang/natThrowable.cc
deleted file mode 100644
index c2f7d1b..0000000
--- a/libjava/java/lang/natThrowable.cc
+++ /dev/null
@@ -1,99 +0,0 @@
-// natThrowable.cc - Superclass for all exceptions.
-
-/* Copyright (C) 2000 Free Software Foundation, Inc
-
- This file is part of libgcj.
-
-This software is copyrighted work licensed under the terms of the
-Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
-details. */
-
-/**
- * @author Andrew Haley <aph@cygnus.com>
- * @date Jan 6 2000
- */
-
-#include <config.h>
-
-#include <string.h>
-
-#include <gcj/cni.h>
-#include <jvm.h>
-#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>
-
-#include <sys/types.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include <unistd.h>
-
-#ifdef HAVE_EXECINFO_H
-#include <execinfo.h>
-#endif
-
-#include <name-finder.h>
-
-/* FIXME: size of the stack trace is limited to 128 elements. It's
- undoubtedly sensible to limit the stack trace, but 128 is rather
- arbitrary. It may be better to configure this. */
-
-java::lang::Throwable *
-java::lang::Throwable::fillInStackTrace (void)
-{
- if (! trace_enabled)
- return this;
-#if defined (HAVE_BACKTRACE)
- void *p[128];
-
- // We subtract 1 from the number of elements because we don't want
- // to include the call to fillInStackTrace in the trace.
- int n = backtrace (p, 128) - 1;
-
- if (n > 0)
- {
- // We copy the array below to deal with alignment issues.
- stackTraceBytes = JvNewByteArray (n * sizeof p[0]);
- memcpy (elements (stackTraceBytes), p+1, (n * sizeof p[0]));
- }
-
-#endif
-
- return this;
-}
-
-JArray<java::lang::StackTraceElement*> *
-java::lang::Throwable::getStackTrace0 ()
-{
-#ifdef HAVE_BACKTRACE
- if (!stackTraceBytes)
- 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++)
- el[i] = finder.lookup (p[i]);
-
- return result;
-#else
- return NULL;
-#endif /* HAVE_BACKTRACE */
-}
diff --git a/libjava/java/lang/natVMThrowable.cc b/libjava/java/lang/natVMThrowable.cc
new file mode 100644
index 0000000..358bab7
--- /dev/null
+++ b/libjava/java/lang/natVMThrowable.cc
@@ -0,0 +1,73 @@
+// natVMThrowable.cc - native helper methods for Throwable
+
+/* Copyright (C) 2000, 2002 Free Software Foundation, Inc
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+/**
+ * @author Andrew Haley <aph@cygnus.com>
+ * @author Mark Wielaard <mark@klomp.org>
+ *
+ * Native helper methods for VM specific Throwable support.
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <jvm.h>
+#include <gcj/cni.h>
+#include <gnu/gcj/RawData.h>
+#include <java/lang/Object.h>
+#include <java-threads.h>
+#include <java/lang/Throwable.h>
+#include <java/lang/VMThrowable.h>
+
+#include <sys/types.h>
+
+#include <stdlib.h>
+
+#include <unistd.h>
+
+#ifdef HAVE_EXECINFO_H
+#include <execinfo.h>
+#endif
+
+/* FIXME: size of the stack trace is limited to 128 elements. It's
+ undoubtedly sensible to limit the stack trace, but 128 is rather
+ arbitrary. It may be better to configure this. */
+
+java::lang::VMThrowable *
+java::lang::VMThrowable::fillInStackTrace (java::lang::Throwable* t)
+{
+ if (! trace_enabled)
+ return NULL;
+#if defined (HAVE_BACKTRACE)
+ VMThrowable* state = new VMThrowable;
+ void *p[128];
+
+ // We subtract 1 from the number of elements because we don't want
+ // to include the calls to fillInStackTrace in the trace.
+ int n = backtrace (p, 128) - 1;
+
+ void **addrs;
+ if (n > 0)
+ {
+ state->length = n;
+ addrs = (void **) _Jv_Malloc (n * sizeof p[0]);
+ while (n--)
+ addrs[n] = p[n];
+ }
+ else
+ addrs = NULL;
+
+ state->stackTraceAddrs = reinterpret_cast<gnu::gcj::RawData *> (addrs);
+
+ return state;
+#endif
+ return NULL;
+}