summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
authorMark Wielaard <mark@klomp.org>2006-04-12 12:04:16 +0000
committerMark Wielaard <mark@klomp.org>2006-04-12 12:04:16 +0000
commitb90cc775e4018e9eb6f9c9edafcdb91b33272f04 (patch)
tree6869727a18dbd5e0ad45ba0284a7929469dd9914 /java
parentdf77b05f70aec916b512d178b2d611ed9a492656 (diff)
downloadclasspath-b90cc775e4018e9eb6f9c9edafcdb91b33272f04.tar.gz
2006-04-12 Mark Wielaard <mark@klomp.org>
Port UncaughtExceptionHandler support from generics branch. * NEWS: Document Thread.UncaughtExceptionHandler VMThread change. 2006-04-12 Andrew John Hughes <gnu_andrew@member.fsf.org> * java/lang/Thread.java: (setUncaughtExceptionHandler(UncaughtExceptionHandler): Added docs and security check. (getUncaughtExceptionHandler()): Documented. (setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler): Added docs and security check. (getDefaultUncaughtExceptionHandler()): Documented. (getId()): Documented. 2006-04-12 Tom Tromey <tromey@redhat.com> * vm/reference/java/lang/VMThread.java (run): Use thread's uncaught handler. * java/lang/Thread.java (defaultHandler): New field. (setDefaultUncaughtExceptionHandler, getDefaultUncaughtExceptionHandler, setUncaughtExceptionHandler, getUncaughtExceptionHandler): New methods. * java/lang/ThreadGroup.java (ThreadGroup): Implements UncaughtExceptionHandler. (uncaughtException): Use getDefaultUncaughtExceptionHandler.
Diffstat (limited to 'java')
-rw-r--r--java/lang/Thread.java178
-rw-r--r--java/lang/ThreadGroup.java5
2 files changed, 181 insertions, 2 deletions
diff --git a/java/lang/Thread.java b/java/lang/Thread.java
index 76df1037b..34825e3cd 100644
--- a/java/lang/Thread.java
+++ b/java/lang/Thread.java
@@ -1,5 +1,5 @@
/* Thread -- an independent thread of executable code
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation
This file is part of GNU Classpath.
@@ -81,6 +81,7 @@ import java.util.Map;
* @author Tom Tromey
* @author John Keiser
* @author Eric Blake (ebb9@email.byu.edu)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @see Runnable
* @see Runtime#exit(int)
* @see #run()
@@ -130,15 +131,27 @@ public class Thread implements Runnable
/** The context classloader for this Thread. */
private ClassLoader contextClassLoader;
+
+ /** This thread's ID. */
+ private final long threadId;
/** The next thread number to use. */
private static int numAnonymousThreadsCreated;
+
+ /** The next thread ID to use. */
+ private static long nextThreadId;
+
+ /** The default exception handler. */
+ private static UncaughtExceptionHandler defaultHandler;
/** Thread local storage. Package accessible for use by
* InheritableThreadLocal.
*/
WeakIdentityHashMap locals;
+ /** The uncaught exception handler. */
+ UncaughtExceptionHandler exceptionHandler;
+
/**
* Allocates a new <code>Thread</code> object. This constructor has
* the same effect as <code>Thread(null, null,</code>
@@ -342,6 +355,11 @@ public class Thread implements Runnable
this.name = name.toString();
this.runnable = target;
this.stacksize = size;
+
+ synchronized (Thread.class)
+ {
+ this.threadId = nextThreadId++;
+ }
priority = current.priority;
daemon = current.daemon;
@@ -371,6 +389,11 @@ public class Thread implements Runnable
this.priority = priority;
this.daemon = daemon;
this.contextClassLoader = ClassLoader.getSystemClassLoader();
+ synchronized (Thread.class)
+ {
+ this.threadId = nextThreadId++;
+ }
+
}
/**
@@ -1000,4 +1023,157 @@ public class Thread implements Runnable
}
return locals;
}
+
+ /**
+ * Assigns the given <code>UncaughtExceptionHandler</code> to this
+ * thread. This will then be called if the thread terminates due
+ * to an uncaught exception, pre-empting that of the
+ * <code>ThreadGroup</code>.
+ *
+ * @param h the handler to use for this thread.
+ * @throws SecurityException if the current thread can't modify this thread.
+ * @since 1.5
+ */
+ public void setUncaughtExceptionHandler(UncaughtExceptionHandler h)
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe.
+ if (sm != null)
+ sm.checkAccess(this);
+ exceptionHandler = h;
+ }
+
+ /**
+ * <p>
+ * Returns the handler used when this thread terminates due to an
+ * uncaught exception. The handler used is determined by the following:
+ * </p>
+ * <ul>
+ * <li>If this thread has its own handler, this is returned.</li>
+ * <li>If not, then the handler of the thread's <code>ThreadGroup</code>
+ * object is returned.</li>
+ * <li>If both are unavailable, then <code>null</code> is returned.</li>
+ * </ul>
+ *
+ * @return the appropriate <code>UncaughtExceptionHandler</code> or
+ * <code>null</code> if one can't be obtained.
+ * @since 1.5
+ */
+ public UncaughtExceptionHandler getUncaughtExceptionHandler()
+ {
+ return exceptionHandler;
+ }
+
+ /**
+ * <p>
+ * Sets the default uncaught exception handler used when one isn't
+ * provided by the thread or its associated <code>ThreadGroup</code>.
+ * This exception handler is used when the thread itself does not
+ * have an exception handler, and the thread's <code>ThreadGroup</code>
+ * does not override this default mechanism with its own. As the group
+ * calls this handler by default, this exception handler should not defer
+ * to that of the group, as it may lead to infinite recursion.
+ * </p>
+ * <p>
+ * Uncaught exception handlers are used when a thread terminates due to
+ * an uncaught exception. Replacing this handler allows default code to
+ * be put in place for all threads in order to handle this eventuality.
+ * </p>
+ *
+ * @param h the new default uncaught exception handler to use.
+ * @throws SecurityException if a security manager is present and
+ * disallows the runtime permission
+ * "setDefaultUncaughtExceptionHandler".
+ * @since 1.5
+ */
+ public static void
+ setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler h)
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe.
+ if (sm != null)
+ sm.checkPermission(new RuntimePermission("setDefaultUncaughtExceptionHandler"));
+ defaultHandler = h;
+ }
+
+ /**
+ * Returns the handler used by default when a thread terminates
+ * unexpectedly due to an exception, or <code>null</code> if one doesn't
+ * exist.
+ *
+ * @return the default uncaught exception handler.
+ * @since 1.5
+ */
+ public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler()
+ {
+ return defaultHandler;
+ }
+
+ /**
+ * Returns the unique identifier for this thread. This ID is generated
+ * on thread creation, and may be re-used on its death.
+ *
+ * @return a positive long number representing the thread's ID.
+ * @since 1.5
+ */
+ public long getId()
+ {
+ return threadId;
+ }
+
+ /**
+ * <p>
+ * This interface is used to handle uncaught exceptions
+ * which cause a <code>Thread</code> to terminate. When
+ * a thread, t, is about to terminate due to an uncaught
+ * exception, the virtual machine looks for a class which
+ * implements this interface, in order to supply it with
+ * the dying thread and its uncaught exception.
+ * </p>
+ * <p>
+ * The virtual machine makes two attempts to find an
+ * appropriate handler for the uncaught exception, in
+ * the following order:
+ * </p>
+ * <ol>
+ * <li>
+ * <code>t.getUncaughtExceptionHandler()</code> --
+ * the dying thread is queried first for a handler
+ * specific to that thread.
+ * </li>
+ * <li>
+ * <code>t.getThreadGroup()</code> --
+ * the thread group of the dying thread is used to
+ * handle the exception. If the thread group has
+ * no special requirements for handling the exception,
+ * it may simply forward it on to
+ * <code>Thread.getDefaultUncaughtExceptionHandler()</code>,
+ * the default handler, which is used as a last resort.
+ * </li>
+ * </ol>
+ * <p>
+ * The first handler found is the one used to handle
+ * the uncaught exception.
+ * </p>
+ *
+ * @author Tom Tromey <tromey@redhat.com>
+ * @author Andrew John Hughes <gnu_andrew@member.fsf.org>
+ * @since 1.5
+ * @see Thread#getUncaughtExceptionHandler()
+ * @see Thread#setUncaughtExceptionHander(java.lang.Thread.UncaughtExceptionHandler)
+ * @see Thread#getDefaultUncaughtExceptionHandler()
+ * @see
+ * Thread#setDefaultUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler)
+ */
+ public interface UncaughtExceptionHandler
+ {
+ /**
+ * Invoked by the virtual machine with the dying thread
+ * and the uncaught exception. Any exceptions thrown
+ * by this method are simply ignored by the virtual
+ * machine.
+ *
+ * @param thr the dying thread.
+ * @param exc the uncaught exception.
+ */
+ void uncaughtException(Thread thr, Throwable exc);
+ }
}
diff --git a/java/lang/ThreadGroup.java b/java/lang/ThreadGroup.java
index 6e4c27a71..7fbef88f4 100644
--- a/java/lang/ThreadGroup.java
+++ b/java/lang/ThreadGroup.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package java.lang;
+import java.lang.Thread.UncaughtExceptionHandler;
import java.util.Vector;
/**
@@ -53,7 +54,7 @@ import java.util.Vector;
* @since 1.0
* @status updated to 1.4
*/
-public class ThreadGroup
+public class ThreadGroup implements UncaughtExceptionHandler
{
/** The Initial, top-level ThreadGroup. */
static ThreadGroup root = new ThreadGroup();
@@ -545,6 +546,8 @@ public class ThreadGroup
{
if (parent != null)
parent.uncaughtException(thread, t);
+ else if (Thread.getDefaultUncaughtExceptionHandler() != null)
+ Thread.getDefaultUncaughtExceptionHandler().uncaughtException(thread, t);
else if (! (t instanceof ThreadDeath))
{
if (t == null)