Index: java/lang/Thread.java =================================================================== RCS file: /cvsroot/classpath/classpath/java/lang/Thread.java,v retrieving revision 1.2 diff -u -b -B -r1.2 Thread.java --- java/lang/Thread.java 21 Nov 2003 08:08:00 -0000 1.2 +++ java/lang/Thread.java 28 Jan 2004 19:37:34 -0000 @@ -1,5 +1,6 @@ /* Thread -- an independent thread of executable code - Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 + Free Software Foundation This file is part of GNU Classpath. @@ -37,6 +38,14 @@ package java.lang; +/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 + * "The Java Language Specification", ISBN 0-201-63451-1 + * plus online API docs for JDK 1.2 beta from http://www.javasoft.com. + * Status: Believed complete to version 1.4, with caveats. We do not + * implement the deprecated (and dangerous) stop, suspend, and resume + * methods. Security implementation is not complete. + */ + /** * Thread represents a single thread of execution in the VM. When an * application VM starts up, it creates a non-daemon Thread which calls the @@ -65,6 +74,7 @@ * or interrupted? The only thing that is clear is that the Thread should be * removed when it is stopped. * + * @author Tom Tromey * @author John Keiser * @author Eric Blake
* @see Runnable @@ -310,6 +320,51 @@ } /** + * Get the number of active threads in the current Thread's ThreadGroup. + * This implementation calls + *currentThread().getThreadGroup().activeCount()
.
+ *
+ * @return the number of active threads in the current ThreadGroup
+ * @see ThreadGroup#activeCount()
+ */
+ public static int activeCount()
+ {
+ return currentThread().group.activeCount();
+ }
+
+ /**
+ * Check whether the current Thread is allowed to modify this Thread. This
+ * passes the check on to SecurityManager.checkAccess(this)
.
+ *
+ * @throws SecurityException if the current Thread cannot modify this Thread
+ * @see SecurityManager#checkAccess(Thread)
+ */
+ public final void checkAccess()
+ {
+ // Bypass System.getSecurityManager, for bootstrap efficiency.
+ SecurityManager sm = Runtime.securityManager;
+ if (sm != null)
+ sm.checkAccess(this);
+ }
+
+ /**
+ * Count the number of stack frames in this Thread. The Thread in question
+ * must be suspended when this occurs.
+ *
+ * @return the number of stack frames in this Thread
+ * @throws IllegalThreadStateException if this Thread is not suspended
+ * @deprecated pointless, since suspend is deprecated
+ */
+ public int countStackFrames()
+ {
+ VMThread t = vmThread;
+ if (t == null || group == null)
+ throw new IllegalThreadStateException();
+
+ return t.countStackFrames();
+ }
+
+ /**
* Get the currently executing Thread. In the situation that the
* currently running thread was created by native code and doesn't
* have an associated Thread object yet, a new Thread object is
@@ -323,162 +378,88 @@
}
/**
- * Yield to another thread. The Thread will not lose any locks it holds
- * during this time. There are no guarantees which thread will be
- * next to run, and it could even be this one, but most VMs will choose
- * the highest priority thread that has been waiting longest.
+ * Originally intended to destroy this thread, this method was never
+ * implemented by Sun, and is hence a no-op.
*/
- public static void yield()
+ public void destroy()
{
- VMThread.yield();
}
/**
- * Suspend the current Thread's execution for the specified amount of
- * time. The Thread will not lose any locks it has during this time. There
- * are no guarantees which thread will be next to run, but most VMs will
- * choose the highest priority thread that has been waiting longest.
+ * Print a stack trace of the current thread to stderr using the same
+ * format as Throwable's printStackTrace() method.
*
- * @param ms the number of milliseconds to sleep, or 0 for forever
- * @throws InterruptedException if the Thread is interrupted; it's
- * interrupted status will be cleared
- * @see #notify()
- * @see #wait(long)
+ * @see Throwable#printStackTrace()
*/
- public static void sleep(long ms) throws InterruptedException
+ public static void dumpStack()
{
- sleep(ms, 0);
+ new Throwable().printStackTrace();
}
/**
- * Suspend the current Thread's execution for the specified amount of
- * time. The Thread will not lose any locks it has during this time. There
- * are no guarantees which thread will be next to run, but most VMs will
- * choose the highest priority thread that has been waiting longest.
- *
- * Note that 1,000,000 nanoseconds == 1 millisecond, but most VMs do
- * not offer that fine a grain of timing resolution. Besides, there is
- * no guarantee that this thread can start up immediately when time expires,
- * because some other thread may be active. So don't expect real-time
- * performance.
+ * Copy every active thread in the current Thread's ThreadGroup into the
+ * array. Extra threads are silently ignored. This implementation calls
+ * getThreadGroup().enumerate(array)
, which may have a
+ * security check, checkAccess(group)
.
*
- * @param ms the number of milliseconds to sleep, or 0 for forever
- * @param ns the number of extra nanoseconds to sleep (0-999999)
- * @throws InterruptedException if the Thread is interrupted; it's
- * interrupted status will be cleared
- * @throws IllegalArgumentException if ns is invalid
- * @see #notify()
- * @see #wait(long, int)
+ * @param array the array to place the Threads into
+ * @return the number of Threads placed into the array
+ * @throws NullPointerException if array is null
+ * @throws SecurityException if you cannot access the ThreadGroup
+ * @see ThreadGroup#enumerate(Thread[])
+ * @see #activeCount()
+ * @see SecurityManager#checkAccess(ThreadGroup)
*/
- public static void sleep(long ms, int ns) throws InterruptedException
+ public static int enumerate(Thread[] array)
{
- VMThread.sleep(ms, ns);
+ return currentThread().group.enumerate(array);
}
/**
- * Start this Thread, calling the run() method of the Runnable this Thread
- * was created with, or else the run() method of the Thread itself. This
- * is the only way to start a new thread; calling run by yourself will just
- * stay in the same thread. The virtual machine will remove the thread from
- * its thread group when the run() method completes.
+ * Get this Thread's name.
*
- * @throws IllegalThreadStateException if the thread has already started
- * @see #run()
+ * @return this Thread's name
*/
- public synchronized void start()
+ public final String getName()
{
- if (vmThread != null || group == null)
- throw new IllegalThreadStateException();
-
- VMThread.create(this, stacksize);
+ VMThread t = vmThread;
+ return t == null ? name : t.getName();
}
/**
- * The method of Thread that will be run if there is no Runnable object
- * associated with the Thread. Thread's implementation does nothing at all.
+ * Get this Thread's priority.
*
- * @see #start()
- * @see #Thread(ThreadGroup, Runnable, String)
+ * @return the Thread's priority
*/
- public void run()
+ public final synchronized int getPriority()
{
- if (toRun != null)
- toRun.run();
+ VMThread t = vmThread;
+ return t == null ? priority : t.getPriority();
}
/**
- * Cause this Thread to stop abnormally because of the throw of a ThreadDeath
- * error. If you stop a Thread that has not yet started, it will stop
- * immediately when it is actually started.
- *
- *
This is inherently unsafe, as it can interrupt synchronized blocks and
- * leave data in bad states. Hence, there is a security check:
- * checkAccess(this)
, plus another one if the current thread
- * is not this: RuntimePermission("stopThread")
. If you must
- * catch a ThreadDeath, be sure to rethrow it after you have cleaned up.
- * ThreadDeath is the only exception which does not print a stack trace when
- * the thread dies.
+ * Get the ThreadGroup this Thread belongs to. If the thread has died, this
+ * returns null.
*
- * @throws SecurityException if you cannot stop the Thread
- * @see #interrupt()
- * @see #checkAccess()
- * @see #start()
- * @see ThreadDeath
- * @see ThreadGroup#uncaughtException(Thread, Throwable)
- * @see SecurityManager#checkAccess(Thread)
- * @see SecurityManager#checkPermission(Permission)
- * @deprecated unsafe operation, try not to use
+ * @return this Thread's ThreadGroup
*/
- public final void stop()
+ public final ThreadGroup getThreadGroup()
{
- stop(new ThreadDeath());
+ return group;
}
/**
- * Cause this Thread to stop abnormally and throw the specified exception.
- * If you stop a Thread that has not yet started, the stop is ignored
- * (contrary to what the JDK documentation says).
- * WARNINGThis bypasses Java security, and can throw a checked
- * exception which the call stack is unprepared to handle. Do not abuse
- * this power.
- *
- *
This is inherently unsafe, as it can interrupt synchronized blocks and
- * leave data in bad states. Hence, there is a security check:
- * checkAccess(this)
, plus another one if the current thread
- * is not this: RuntimePermission("stopThread")
. If you must
- * catch a ThreadDeath, be sure to rethrow it after you have cleaned up.
- * ThreadDeath is the only exception which does not print a stack trace when
- * the thread dies.
+ * Checks whether the current thread holds the monitor on a given object.
+ * This allows you to do assert Thread.holdsLock(obj)
.
*
- * @param t the Throwable to throw when the Thread dies
- * @throws SecurityException if you cannot stop the Thread
- * @throws NullPointerException in the calling thread, if t is null
- * @see #interrupt()
- * @see #checkAccess()
- * @see #start()
- * @see ThreadDeath
- * @see ThreadGroup#uncaughtException(Thread, Throwable)
- * @see SecurityManager#checkAccess(Thread)
- * @see SecurityManager#checkPermission(Permission)
- * @deprecated unsafe operation, try not to use
+ * @param obj the object to check
+ * @return true if the current thread is currently synchronized on obj
+ * @throws NullPointerException if obj is null
+ * @since 1.4
*/
- public final synchronized void stop(Throwable t)
- {
- if (t == null)
- throw new NullPointerException();
- // Bypass System.getSecurityManager, for bootstrap efficiency.
- SecurityManager sm = Runtime.securityManager;
- if (sm != null)
+ public static boolean holdsLock(Object obj)
{
- sm.checkAccess(this);
- if (this != currentThread())
- sm.checkPermission(new RuntimePermission("stopThread"));
- }
- VMThread vt = vmThread;
- if (vt != null)
- vt.stop(t);
- else
- stillborn = t;
+ return VMThread.holdsLock(obj);
}
/**
@@ -537,14 +518,6 @@
}
/**
- * Originally intended to destroy this thread, this method was never
- * implemented by Sun, and is hence a no-op.
- */
- public void destroy()
- {
- }
-
- /**
* Determine whether this Thread is alive. A thread which is alive has
* started and not yet died.
*
@@ -556,188 +529,213 @@
}
/**
- * Suspend this Thread. It will not come back, ever, unless it is resumed.
- *
- *
This is inherently unsafe, as the suspended thread still holds locks,
- * and can potentially deadlock your program. Hence, there is a security
- * check: checkAccess
.
+ * Tell whether this is a daemon Thread or not.
*
- * @throws SecurityException if you cannot suspend the Thread
- * @see #checkAccess()
- * @see #resume()
- * @deprecated unsafe operation, try not to use
+ * @return whether this is a daemon Thread or not
+ * @see #setDaemon(boolean)
*/
- public final synchronized void suspend()
+ public final boolean isDaemon()
{
- checkAccess();
VMThread t = vmThread;
- if (t != null)
- t.suspend();
+ return t == null ? daemon : t.isDaemon();
}
/**
- * Resume this Thread. If the thread is not suspended, this method does
- * nothing. To mirror suspend(), there may be a security check:
- * checkAccess
.
+ * Wait forever for the Thread in question to die.
*
- * @throws SecurityException if you cannot resume the Thread
- * @see #checkAccess()
- * @see #suspend()
- * @deprecated pointless, since suspend is deprecated
+ * @throws InterruptedException if the Thread is interrupted; it's
+ * interrupted status will be cleared
*/
- public final synchronized void resume()
+ public final void join() throws InterruptedException
{
- checkAccess();
- VMThread t = vmThread;
- if (t != null)
- t.resume();
+ join(0, 0);
}
/**
- * Set this Thread's priority. There may be a security check,
- * checkAccess
, then the priority is set to the smaller of
- * priority and the ThreadGroup maximum priority.
+ * Wait the specified amount of time for the Thread in question to die.
*
- * @param priority the new priority for this Thread
- * @throws IllegalArgumentException if priority exceeds MIN_PRIORITY or
- * MAX_PRIORITY
- * @throws SecurityException if you cannot modify this Thread
- * @see #getPriority()
- * @see #checkAccess()
- * @see ThreadGroup#getMaxPriority()
- * @see #MIN_PRIORITY
- * @see #MAX_PRIORITY
+ * @param ms the number of milliseconds to wait, or 0 for forever
+ * @throws InterruptedException if the Thread is interrupted; it's
+ * interrupted status will be cleared
*/
- public final synchronized void setPriority(int priority)
+ public final void join(long ms) throws InterruptedException
{
- checkAccess();
- if (priority < MIN_PRIORITY || priority > MAX_PRIORITY)
- throw new IllegalArgumentException("Invalid thread priority value "
- + priority + ".");
- priority = Math.min(priority, group.getMaxPriority());
- VMThread t = vmThread;
- if (t != null)
- t.setPriority(priority);
- else
- this.priority = priority;
+ join(ms, 0);
}
/**
- * Get this Thread's priority.
+ * Wait the specified amount of time for the Thread in question to die.
*
- * @return the Thread's priority
+ *
Note that 1,000,000 nanoseconds == 1 millisecond, but most VMs do
+ * not offer that fine a grain of timing resolution. Besides, there is
+ * no guarantee that this thread can start up immediately when time expires,
+ * because some other thread may be active. So don't expect real-time
+ * performance.
+ *
+ * @param ms the number of milliseconds to wait, or 0 for forever
+ * @param ns the number of extra nanoseconds to sleep (0-999999)
+ * @throws InterruptedException if the Thread is interrupted; it's
+ * interrupted status will be cleared
+ * @throws IllegalArgumentException if ns is invalid
*/
- public final synchronized int getPriority()
+ public final void join(long ms, int ns) throws InterruptedException
{
+ if(ms < 0 || ns < 0 || ns > 999999)
+ throw new IllegalArgumentException();
+
VMThread t = vmThread;
- return t == null ? priority : t.getPriority();
+ if(t != null)
+ t.join(ms, ns);
}
/**
- * Set this Thread's name. There may be a security check,
+ * Resume this Thread. If the thread is not suspended, this method does
+ * nothing. To mirror suspend(), there may be a security check:
* checkAccess
.
*
- * @param name the new name for this Thread
- * @throws NullPointerException if name is null
- * @throws SecurityException if you cannot modify this Thread
+ * @throws SecurityException if you cannot resume the Thread
+ * @see #checkAccess()
+ * @see #suspend()
+ * @deprecated pointless, since suspend is deprecated
*/
- public final synchronized void setName(String name)
+ public final synchronized void resume()
{
checkAccess();
- // Use toString hack to detect null.
- name = name.toString();
VMThread t = vmThread;
if (t != null)
- t.setName(name);
- else
- this.name = name;
+ t.resume();
}
/**
- * Get this Thread's name.
+ * The method of Thread that will be run if there is no Runnable object
+ * associated with the Thread. Thread's implementation does nothing at all.
*
- * @return this Thread's name
+ * @see #start()
+ * @see #Thread(ThreadGroup, Runnable, String)
*/
- public final String getName()
+ public void run()
{
- VMThread t = vmThread;
- return t == null ? name : t.getName();
+ if (toRun != null)
+ toRun.run();
}
/**
- * Get the ThreadGroup this Thread belongs to. If the thread has died, this
- * returns null.
+ * Set the daemon status of this Thread. If this is a daemon Thread, then
+ * the VM may exit even if it is still running. This may only be called
+ * while the Thread is not running. There may be a security check,
+ * checkAccess
.
*
- * @return this Thread's ThreadGroup
+ * @param daemon whether this should be a daemon thread or not
+ * @throws SecurityException if you cannot modify this Thread
+ * @throws IllegalThreadStateException if the Thread is active
+ * @see #isDaemon()
+ * @see #checkAccess()
*/
- public final ThreadGroup getThreadGroup()
+ public final synchronized void setDaemon(boolean daemon)
{
- return group;
+ if (vmThread != null || group == null)
+ throw new IllegalThreadStateException();
+ checkAccess();
+ this.daemon = daemon;
}
/**
- * Get the number of active threads in the current Thread's ThreadGroup.
- * This implementation calls
- * currentThread().getThreadGroup().activeCount()
.
+ * Returns the context classloader of this Thread. The context
+ * classloader can be used by code that want to load classes depending
+ * on the current thread. Normally classes are loaded depending on
+ * the classloader of the current class. There may be a security check
+ * for RuntimePermission("getClassLoader")
if the caller's
+ * class loader is not null or an ancestor of this thread's context class
+ * loader.
*
- * @return the number of active threads in the current ThreadGroup
- * @see ThreadGroup#activeCount()
+ * @return the context class loader
+ * @throws SecurityException when permission is denied
+ * @see setContextClassLoader(ClassLoader)
+ * @since 1.2
*/
- public static int activeCount()
+ public ClassLoader getContextClassLoader()
{
- return currentThread().group.activeCount();
+ // Bypass System.getSecurityManager, for bootstrap efficiency.
+ SecurityManager sm = Runtime.securityManager;
+ if (sm != null)
+ // XXX Don't check this if the caller's class loader is an ancestor.
+ sm.checkPermission(new RuntimePermission("getClassLoader"));
+ return contextClassLoader;
}
/**
- * Copy every active thread in the current Thread's ThreadGroup into the
- * array. Extra threads are silently ignored. This implementation calls
- * getThreadGroup().enumerate(array)
, which may have a
- * security check, checkAccess(group)
.
+ * Sets the context classloader for this Thread. When not explicitly set,
+ * the context classloader for a thread is the same as the context
+ * classloader of the thread that created this thread. The first thread has
+ * as context classloader the system classloader. There may be a security
+ * check for RuntimePermission("setContextClassLoader")
.
*
- * @param array the array to place the Threads into
- * @return the number of Threads placed into the array
- * @throws NullPointerException if array is null
- * @throws SecurityException if you cannot access the ThreadGroup
- * @see ThreadGroup#enumerate(Thread[])
- * @see #activeCount()
- * @see SecurityManager#checkAccess(ThreadGroup)
+ * @param classloader the new context class loader
+ * @throws SecurityException when permission is denied
+ * @see getContextClassLoader()
+ * @since 1.2
*/
- public static int enumerate(Thread[] array)
+ public void setContextClassLoader(ClassLoader classloader)
{
- return currentThread().group.enumerate(array);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new RuntimePermission("setContextClassLoader"));
+ this.contextClassLoader = classloader;
}
/**
- * Count the number of stack frames in this Thread. The Thread in question
- * must be suspended when this occurs.
+ * Set this Thread's name. There may be a security check,
+ * checkAccess
.
*
- * @return the number of stack frames in this Thread
- * @throws IllegalThreadStateException if this Thread is not suspended
- * @deprecated pointless, since suspend is deprecated
+ * @param name the new name for this Thread
+ * @throws NullPointerException if name is null
+ * @throws SecurityException if you cannot modify this Thread
*/
- public int countStackFrames()
+ public final synchronized void setName(String name)
{
+ checkAccess();
+ // Use toString hack to detect null.
+ name = name.toString();
VMThread t = vmThread;
- if (t == null || group == null)
- throw new IllegalThreadStateException();
+ if (t != null)
+ t.setName(name);
+ else
+ this.name = name;
+ }
- return t.countStackFrames();
+ /**
+ * Yield to another thread. The Thread will not lose any locks it holds
+ * during this time. There are no guarantees which thread will be
+ * next to run, and it could even be this one, but most VMs will choose
+ * the highest priority thread that has been waiting longest.
+ */
+ public static void yield()
+ {
+ VMThread.yield();
}
/**
- * Wait the specified amount of time for the Thread in question to die.
+ * Suspend the current Thread's execution for the specified amount of
+ * time. The Thread will not lose any locks it has during this time. There
+ * are no guarantees which thread will be next to run, but most VMs will
+ * choose the highest priority thread that has been waiting longest.
*
- * @param ms the number of milliseconds to wait, or 0 for forever
+ * @param ms the number of milliseconds to sleep, or 0 for forever
* @throws InterruptedException if the Thread is interrupted; it's
* interrupted status will be cleared
+ * @see #notify()
+ * @see #wait(long)
*/
- public final void join(long ms) throws InterruptedException
+ public static void sleep(long ms) throws InterruptedException
{
- join(ms, 0);
+ sleep(ms, 0);
}
/**
- * Wait the specified amount of time for the Thread in question to die.
+ * Suspend the current Thread's execution for the specified amount of
+ * time. The Thread will not lose any locks it has during this time. There
+ * are no guarantees which thread will be next to run, but most VMs will
+ * choose the highest priority thread that has been waiting longest.
*
*
Note that 1,000,000 nanoseconds == 1 millisecond, but most VMs do
* not offer that fine a grain of timing resolution. Besides, there is
@@ -745,162 +743,174 @@
* because some other thread may be active. So don't expect real-time
* performance.
*
- * @param ms the number of milliseconds to wait, or 0 for forever
+ * @param ms the number of milliseconds to sleep, or 0 for forever
* @param ns the number of extra nanoseconds to sleep (0-999999)
* @throws InterruptedException if the Thread is interrupted; it's
* interrupted status will be cleared
* @throws IllegalArgumentException if ns is invalid
+ * @see #notify()
+ * @see #wait(long, int)
*/
- public final void join(long ms, int ns) throws InterruptedException
+ public static void sleep(long ms, int ns) throws InterruptedException
{
- if(ms < 0 || ns < 0 || ns > 999999)
- throw new IllegalArgumentException();
-
- VMThread t = vmThread;
- if(t != null)
- t.join(ms, ns);
+ VMThread.sleep(ms, ns);
}
/**
- * Wait forever for the Thread in question to die.
+ * Start this Thread, calling the run() method of the Runnable this Thread
+ * was created with, or else the run() method of the Thread itself. This
+ * is the only way to start a new thread; calling run by yourself will just
+ * stay in the same thread. The virtual machine will remove the thread from
+ * its thread group when the run() method completes.
*
- * @throws InterruptedException if the Thread is interrupted; it's
- * interrupted status will be cleared
+ * @throws IllegalThreadStateException if the thread has already started
+ * @see #run()
*/
- public final void join() throws InterruptedException
+ public synchronized void start()
{
- join(0, 0);
- }
+ if (vmThread != null || group == null)
+ throw new IllegalThreadStateException();
- /**
- * Print a stack trace of the current thread to stderr using the same
- * format as Throwable's printStackTrace() method.
- *
- * @see Throwable#printStackTrace()
- */
- public static void dumpStack()
- {
- new Throwable().printStackTrace();
+ VMThread.create(this, stacksize);
}
/**
- * Set the daemon status of this Thread. If this is a daemon Thread, then
- * the VM may exit even if it is still running. This may only be called
- * while the Thread is not running. There may be a security check,
- * checkAccess
.
+ * Cause this Thread to stop abnormally because of the throw of a ThreadDeath
+ * error. If you stop a Thread that has not yet started, it will stop
+ * immediately when it is actually started.
*
- * @param daemon whether this should be a daemon thread or not
- * @throws SecurityException if you cannot modify this Thread
- * @throws IllegalThreadStateException if the Thread is active
- * @see #isDaemon()
+ *
This is inherently unsafe, as it can interrupt synchronized blocks and
+ * leave data in bad states. Hence, there is a security check:
+ * checkAccess(this)
, plus another one if the current thread
+ * is not this: RuntimePermission("stopThread")
. If you must
+ * catch a ThreadDeath, be sure to rethrow it after you have cleaned up.
+ * ThreadDeath is the only exception which does not print a stack trace when
+ * the thread dies.
+ *
+ * @throws SecurityException if you cannot stop the Thread
+ * @see #interrupt()
* @see #checkAccess()
+ * @see #start()
+ * @see ThreadDeath
+ * @see ThreadGroup#uncaughtException(Thread, Throwable)
+ * @see SecurityManager#checkAccess(Thread)
+ * @see SecurityManager#checkPermission(Permission)
+ * @deprecated unsafe operation, try not to use
*/
- public final synchronized void setDaemon(boolean daemon)
+ public final void stop()
{
- if (vmThread != null || group == null)
- throw new IllegalThreadStateException();
- checkAccess();
- this.daemon = daemon;
+ stop(new ThreadDeath());
}
/**
- * Tell whether this is a daemon Thread or not.
+ * Cause this Thread to stop abnormally and throw the specified exception.
+ * If you stop a Thread that has not yet started, the stop is ignored
+ * (contrary to what the JDK documentation says).
+ * WARNINGThis bypasses Java security, and can throw a checked
+ * exception which the call stack is unprepared to handle. Do not abuse
+ * this power.
*
- * @return whether this is a daemon Thread or not
- * @see #setDaemon(boolean)
- */
- public final boolean isDaemon()
- {
- VMThread t = vmThread;
- return t == null ? daemon : t.isDaemon();
- }
-
- /**
- * Check whether the current Thread is allowed to modify this Thread. This
- * passes the check on to SecurityManager.checkAccess(this)
.
+ *
This is inherently unsafe, as it can interrupt synchronized blocks and
+ * leave data in bad states. Hence, there is a security check:
+ * checkAccess(this)
, plus another one if the current thread
+ * is not this: RuntimePermission("stopThread")
. If you must
+ * catch a ThreadDeath, be sure to rethrow it after you have cleaned up.
+ * ThreadDeath is the only exception which does not print a stack trace when
+ * the thread dies.
*
- * @throws SecurityException if the current Thread cannot modify this Thread
+ * @param t the Throwable to throw when the Thread dies
+ * @throws SecurityException if you cannot stop the Thread
+ * @throws NullPointerException in the calling thread, if t is null
+ * @see #interrupt()
+ * @see #checkAccess()
+ * @see #start()
+ * @see ThreadDeath
+ * @see ThreadGroup#uncaughtException(Thread, Throwable)
* @see SecurityManager#checkAccess(Thread)
+ * @see SecurityManager#checkPermission(Permission)
+ * @deprecated unsafe operation, try not to use
*/
- public final void checkAccess()
+ public final synchronized void stop(Throwable t)
{
+ if (t == null)
+ throw new NullPointerException();
// Bypass System.getSecurityManager, for bootstrap efficiency.
SecurityManager sm = Runtime.securityManager;
if (sm != null)
+ {
sm.checkAccess(this);
+ if (this != currentThread())
+ sm.checkPermission(new RuntimePermission("stopThread"));
}
-
- /**
- * Return a human-readable String representing this Thread. The format of
- * the string is:
- * "Thread[" + getName() + ',' + getPriority() + ','
- * + (getThreadGroup() == null ? "" : getThreadGroup().getName())
- + ']'
.
- *
- * @return a human-readable String representing this Thread
- */
- public String toString()
- {
- return "Thread[" + name + ',' + priority + ','
- + (group == null ? "" : group.name) + ']';
+ VMThread vt = vmThread;
+ if (vt != null)
+ vt.stop(t);
+ else
+ stillborn = t;
}
/**
- * Returns the context classloader of this Thread. The context
- * classloader can be used by code that want to load classes depending
- * on the current thread. Normally classes are loaded depending on
- * the classloader of the current class. There may be a security check
- * for RuntimePermission("getClassLoader")
if the caller's
- * class loader is not null or an ancestor of this thread's context class
- * loader.
+ * Suspend this Thread. It will not come back, ever, unless it is resumed.
*
- * @return the context class loader
- * @throws SecurityException when permission is denied
- * @see setContextClassLoader(ClassLoader)
- * @since 1.2
+ *
This is inherently unsafe, as the suspended thread still holds locks,
+ * and can potentially deadlock your program. Hence, there is a security
+ * check: checkAccess
.
+ *
+ * @throws SecurityException if you cannot suspend the Thread
+ * @see #checkAccess()
+ * @see #resume()
+ * @deprecated unsafe operation, try not to use
*/
- public ClassLoader getContextClassLoader()
+ public final synchronized void suspend()
{
- // Bypass System.getSecurityManager, for bootstrap efficiency.
- SecurityManager sm = Runtime.securityManager;
- if (sm != null)
- // XXX Don't check this if the caller's class loader is an ancestor.
- sm.checkPermission(new RuntimePermission("getClassLoader"));
- return contextClassLoader;
+ checkAccess();
+ VMThread t = vmThread;
+ if (t != null)
+ t.suspend();
}
/**
- * Sets the context classloader for this Thread. When not explicitly set,
- * the context classloader for a thread is the same as the context
- * classloader of the thread that created this thread. The first thread has
- * as context classloader the system classloader. There may be a security
- * check for RuntimePermission("setContextClassLoader")
.
+ * Set this Thread's priority. There may be a security check,
+ * checkAccess
, then the priority is set to the smaller of
+ * priority and the ThreadGroup maximum priority.
*
- * @param classloader the new context class loader
- * @throws SecurityException when permission is denied
- * @see getContextClassLoader()
- * @since 1.2
+ * @param priority the new priority for this Thread
+ * @throws IllegalArgumentException if priority exceeds MIN_PRIORITY or
+ * MAX_PRIORITY
+ * @throws SecurityException if you cannot modify this Thread
+ * @see #getPriority()
+ * @see #checkAccess()
+ * @see ThreadGroup#getMaxPriority()
+ * @see #MIN_PRIORITY
+ * @see #MAX_PRIORITY
*/
- public void setContextClassLoader(ClassLoader classloader)
+ public final synchronized void setPriority(int priority)
{
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- sm.checkPermission(new RuntimePermission("setContextClassLoader"));
- this.contextClassLoader = classloader;
+ checkAccess();
+ if (priority < MIN_PRIORITY || priority > MAX_PRIORITY)
+ throw new IllegalArgumentException("Invalid thread priority value "
+ + priority + ".");
+ priority = Math.min(priority, group.getMaxPriority());
+ VMThread t = vmThread;
+ if (t != null)
+ t.setPriority(priority);
+ else
+ this.priority = priority;
}
/**
- * Checks whether the current thread holds the monitor on a given object.
- * This allows you to do assert Thread.holdsLock(obj)
.
+ * Return a human-readable String representing this Thread. The format of
+ * the string is:
+ * "Thread[" + getName() + ',' + getPriority() + ','
+ * + (getThreadGroup() == null ? "" : getThreadGroup().getName())
+ + ']'
.
*
- * @param obj the object to check
- * @return true if the current thread is currently synchronized on obj
- * @throws NullPointerException if obj is null
- * @since 1.4
+ * @return a human-readable String representing this Thread
*/
- public static boolean holdsLock(Object obj)
+ public String toString()
{
- return VMThread.holdsLock(obj);
+ return ("Thread[" + name + "," + priority + "," +
+ (group == null ? "" : group.getName()) + "]");
}
/**
@@ -911,4 +921,4 @@
group.removeThread(this);
vmThread = null;
}
-} // class Thread
+}