diff options
author | Mark Wielaard <mark@klomp.org> | 2002-08-24 22:46:19 +0000 |
---|---|---|
committer | Mark Wielaard <mark@gcc.gnu.org> | 2002-08-24 22:46:19 +0000 |
commit | 6e0532cdf6f9fb4776bfa0f05a29c06a362d466b (patch) | |
tree | 2194f5746d8d192d6202800f3df90a8ccb1675e0 /libjava/java/lang | |
parent | 4906d5d83e08494b70297808d6818faffd89c2a0 (diff) | |
download | gcc-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.java | 160 | ||||
-rw-r--r-- | libjava/java/lang/VMThrowable.java | 97 | ||||
-rw-r--r-- | libjava/java/lang/natThrowable.cc | 99 | ||||
-rw-r--r-- | libjava/java/lang/natVMThrowable.cc | 73 |
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; +} |