/* * @(#)Thread.java 1.145 06/10/10 * * Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program 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 version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. * */ package java.lang; import java.security.AccessController; import java.security.AccessControlContext; import java.util.Map; import java.util.Collections; import sun.misc.CVM; import sun.misc.ThreadRegistry; import sun.security.util.SecurityConstants; /** * A <i>thread</i> is a thread of execution in a program. The Java * Virtual Machine allows an application to have multiple threads of * execution running concurrently. * <p> * Every thread has a priority. Threads with higher priority are * executed in preference to threads with lower priority. Each thread * may or may not also be marked as a daemon. When code running in * some thread creates a new <code>Thread</code> object, the new * thread has its priority initially set equal to the priority of the * creating thread, and is a daemon thread if and only if the * creating thread is a daemon. * <p> * When a Java Virtual Machine starts up, there is usually a single * non-daemon thread (which typically calls the method named * <code>main</code> of some designated class). The Java Virtual * Machine continues to execute threads until either of the following * occurs: * <ul> * <li>The <code>exit</code> method of class <code>Runtime</code> has been * called and the security manager has permitted the exit operation * to take place. * <li>All threads that are not daemon threads have died, either by * returning from the call to the <code>run</code> method or by * throwing an exception that propagates beyond the <code>run</code> * method. * </ul> * <p> * There are two ways to create a new thread of execution. One is to * declare a class to be a subclass of <code>Thread</code>. This * subclass should override the <code>run</code> method of class * <code>Thread</code>. An instance of the subclass can then be * allocated and started. For example, a thread that computes primes * larger than a stated value could be written as follows: * <p><hr><blockquote><pre> * class PrimeThread extends Thread { * long minPrime; * PrimeThread(long minPrime) { * this.minPrime = minPrime; * } * * public void run() { * // compute primes larger than minPrime *  . . . * } * } * </pre></blockquote><hr> * <p> * The following code would then create a thread and start it running: * <p><blockquote><pre> * PrimeThread p = new PrimeThread(143); * p.start(); * </pre></blockquote> * <p> * The other way to create a thread is to declare a class that * implements the <code>Runnable</code> interface. That class then * implements the <code>run</code> method. An instance of the class can * then be allocated, passed as an argument when creating * <code>Thread</code>, and started. The same example in this other * style looks like the following: * <p><hr><blockquote><pre> * class PrimeRun implements Runnable { * long minPrime; * PrimeRun(long minPrime) { * this.minPrime = minPrime; * } * * public void run() { * // compute primes larger than minPrime *  . . . * } * } * </pre></blockquote><hr> * <p> * The following code would then create a thread and start it running: * <p><blockquote><pre> * PrimeRun p = new PrimeRun(143); * new Thread(p).start(); * </pre></blockquote> * <p> * Every thread has a name for identification purposes. More than * one thread may have the same name. If a name is not specified when * a thread is created, a new name is generated for it. * * @author unascribed * @version 1.114, 05/17/00 * @see java.lang.Runnable * @see java.lang.Runtime#exit(int) * @see java.lang.Thread#run() * @since JDK1.0 */ public class Thread implements Runnable { /* Make sure registerNatives is the first thing <clinit> does. */ /* private static native void registerNatives(); static { registerNatives(); } */ private char name[]; private int priority; private long eetop; /* Whether or not to single_step this thread. */ private boolean single_step; /* Whether or not the thread is a daemon thread. */ private boolean daemon = false; /* start() called. */ private boolean alive = false; /* start() called, keeps track that a thread can only be started once */ private boolean hasStartedOnce = false; /* Thread.stop() called. */ private boolean stillborn = false; /* Thread.interrupt() called. */ private boolean wasInterrupted = false; /* Locks for this class. */ private Object lock = new Object(); private static Object staticLock = new Object(); /* What will be run. */ private Runnable target; /* The group of this thread */ private ThreadGroup group; /* The context ClassLoader for this thread */ private ClassLoader contextClassLoader; /* The inherited AccessControlContext of this thread */ private AccessControlContext inheritedAccessControlContext; /* For autonumbering anonymous threads. */ private static int threadInitNumber; private static int nextThreadNum() { synchronized (staticLock) { return threadInitNumber++; } } /* ThreadLocal values pertaining to this thread. This map is maintained * by the ThreadLocal class. */ ThreadLocal.ThreadLocalMap threadLocals = null; /* * InheritableThreadLocal values pertaining to this thread. This map is * maintained by the InheritableThreadLocal class. */ ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; /* * The requested stack size for this thread, or 0 if the creator did * not specify a stack size. It is up to the VM to do whatever it * likes with this number; some VMs will ignore it. */ private long stackSize; /** * The minimum priority that a thread can have. */ public final static int MIN_PRIORITY = 1; /** * The default priority that is assigned to a thread. */ public final static int NORM_PRIORITY = 5; /** * The maximum priority that a thread can have. */ public final static int MAX_PRIORITY = 10; /** * Returns a reference to the currently executing thread object. * * @return the currently executing thread. */ public static native Thread currentThread(); /** * Used to initialize the main thread. */ private static native void setCurrentThread(Thread main); /** * Causes the currently executing thread object to temporarily pause * and allow other threads to execute. */ public static native void yield(); /** * Causes the currently executing thread to sleep (temporarily cease * execution) for the specified number of milliseconds. The thread * does not lose ownership of any monitors. * * @param millis the length of time to sleep in milliseconds. * @exception InterruptedException if another thread has interrupted * the current thread. The <i>interrupted status</i> of the * current thread is cleared when this exception is thrown. * @see java.lang.Object#notify() */ public static void sleep(long millis) throws InterruptedException { if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } sleep0(millis); } private static native void sleep0(long millis) throws InterruptedException; /** * Causes the currently executing thread to sleep (cease execution) * for the specified number of milliseconds plus the specified number * of nanoseconds. The thread does not lose ownership of any monitors. * * @param millis the length of time to sleep in milliseconds. * @param nanos 0-999999 additional nanoseconds to sleep. * @exception IllegalArgumentException if the value of millis is * negative or the value of nanos is not in the range * 0-999999. * @exception InterruptedException if another thread has interrupted * the current thread. The <i>interrupted status</i> of the * current thread is cleared when this exception is thrown. * @see java.lang.Object#notify() */ public static void sleep(long millis, int nanos) throws InterruptedException { if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (nanos < 0 || nanos > 999999) { throw new IllegalArgumentException( "nanosecond timeout value out of range"); } if (nanos >= 500000 || (nanos != 0 && millis == 0)) { millis++; } sleep0(millis); } /** * Initialize a Thread. * * @param g the Thread group * @param target the object whose run() method gets called * @param name the name of the new Thread * @param stackSize the desired stack size for the new thread, or * zero to indicate that this parameter is to be ignored. */ private void init(ThreadGroup g, Runnable target, String name, long stackSize) { /* We don't ever want locking on "lock" to fail, especially when * done during Thread.exit(). */ if (!sun.misc.CVM.objectInflatePermanently(lock)) { throw new OutOfMemoryError(); } Thread parent = currentThread(); if (parent == null) { // must be the main or an attached thread setCurrentThread(this); parent = this; } if (g == null) { /* Determine if it's an applet or not */ SecurityManager security = System.getSecurityManager(); /* If there is a security manager, ask the security manager what to do. */ if (security != null) { g = security.getThreadGroup(); } /* If the security doesn't have a strong opinion of the matter use the parent thread group. */ if (g == null) { g = parent.getThreadGroup(); } } /* checkAccess regardless of whether or not threadgroup is explicitly passed in. */ g.checkAccess(); g.addUnstarted(); this.group = g; this.daemon = parent.isDaemon(); this.name = name.toCharArray(); this.priority = parent.getPriority(); this.contextClassLoader = parent.contextClassLoader; this.inheritedAccessControlContext = AccessController.getContext(); this.target = target; setPriority(priority); if (parent.inheritableThreadLocals != null) this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); /* Stash the specified stack size in case the VM cares */ this.stackSize = stackSize; } private void init(ThreadGroup g, Runnable target, String name) { Thread parent = currentThread(); init(g, target, name, parent.getPriority()); } /** * Allocates a new <code>Thread</code> object. This constructor has * the same effect as <code>Thread(null, null,</code> * <i>gname</i><code>)</code>, where <b><i>gname</i></b> is * a newly generated name. Automatically generated names are of the * form <code>"Thread-"+</code><i>n</i>, where <i>n</i> is an integer. * * @see java.lang.Thread#Thread(java.lang.ThreadGroup, * java.lang.Runnable, java.lang.String) */ public Thread() { init(null, null, "Thread-" + nextThreadNum(), 0); } /** * Allocates a new <code>Thread</code> object. This constructor has * the same effect as <code>Thread(null, target,</code> * <i>gname</i><code>)</code>, where <i>gname</i> is * a newly generated name. Automatically generated names are of the * form <code>"Thread-"+</code><i>n</i>, where <i>n</i> is an integer. * * @param target the object whose <code>run</code> method is called. * @see java.lang.Thread#Thread(java.lang.ThreadGroup, * java.lang.Runnable, java.lang.String) */ public Thread(Runnable target) { init(null, target, "Thread-" + nextThreadNum(), 0); } /** * Allocates a new <code>Thread</code> object. This constructor has * the same effect as <code>Thread(group, target,</code> * <i>gname</i><code>)</code>, where <i>gname</i> is * a newly generated name. Automatically generated names are of the * form <code>"Thread-"+</code><i>n</i>, where <i>n</i> is an integer. * * @param group the thread group. * @param target the object whose <code>run</code> method is called. * @exception SecurityException if the current thread cannot create a * thread in the specified thread group. * @see java.lang.Thread#Thread(java.lang.ThreadGroup, * java.lang.Runnable, java.lang.String) */ public Thread(ThreadGroup group, Runnable target) { init(group, target, "Thread-" + nextThreadNum(), 0); } /** * Allocates a new <code>Thread</code> object. This constructor has * the same effect as <code>Thread(null, null, name)</code>. * * @param name the name of the new thread. * @see java.lang.Thread#Thread(java.lang.ThreadGroup, * java.lang.Runnable, java.lang.String) */ public Thread(String name) { init(null, null, name, 0); } /** * Allocates a new <code>Thread</code> object. This constructor has * the same effect as <code>Thread(group, null, name)</code> * * @param group the thread group. * @param name the name of the new thread. * @exception SecurityException if the current thread cannot create a * thread in the specified thread group. * @see java.lang.Thread#Thread(java.lang.ThreadGroup, * java.lang.Runnable, java.lang.String) */ public Thread(ThreadGroup group, String name) { init(group, null, name, 0); } /* * Private methods and constructor for attaching to existing thread, * used by JNI AttachCurrentThread, etc. */ private static ThreadGroup systemThreadGroup; private static ThreadGroup mainThreadGroup; private Thread(ThreadGroup group, String name, int priority, long eetop) { this.eetop = eetop; this.priority = priority; init(group, null, name, 0); } /* JNI_CreateJavaVM() invokes this */ private static void initMainThread(int priority, long eetop) { systemThreadGroup = new ThreadGroup(); mainThreadGroup = new ThreadGroup(systemThreadGroup, "main"); Thread mainThread = new Thread(mainThreadGroup, "main", priority, eetop); /* The main thread will be alive (alive==true) by default. * Thus need to perform operations normally done in Thread.start(). */ mainThreadGroup.add(mainThread); ThreadRegistry.add(mainThread); mainThread.alive = true; } /* CVMjniAttachCurrentThread() invokes this */ private static Thread initAttachedThread(ThreadGroup group, String name, int priority, long eetop, boolean isDaemon) { if (group == null) { group = mainThreadGroup; } if (name == null) { name = "Thread-" + nextThreadNum(); } Thread attachedThread = new Thread(group, name, priority, eetop); attachedThread.daemon = isDaemon; ThreadRegistry.add(attachedThread); return attachedThread; } /* CVMjvmpi_CreateSystemThread() invokes this */ private static Thread initDaemonThread(String name, int priority) { Thread daemonThread = new Thread(systemThreadGroup, name); daemonThread.priority = priority; daemonThread.daemon = true; ThreadRegistry.add(daemonThread); return daemonThread; } // %begin lvm /* CVMLVMjobjectInitSystemClasses() invokes this to initialize * the newly created LVM context. */ private void reinitLVMStartupThread() { systemThreadGroup = new ThreadGroup(); mainThreadGroup = new ThreadGroup(systemThreadGroup, "main"); if (group != null) { group.remove(this); } group = systemThreadGroup; group.add(this); contextClassLoader = null; inheritedAccessControlContext = null; //threadLocals = Collections.EMPTY_MAP; threadLocals = null; //inheritableThreadLocals = Collections.EMPTY_MAP; inheritableThreadLocals = null; } // %end lvm /** * Allocates a new <code>Thread</code> object. This constructor has * the same effect as <code>Thread(null, target, name)</code>. * * @param target the object whose <code>run</code> method is called. * @param name the name of the new thread. * @see java.lang.Thread#Thread(java.lang.ThreadGroup, * java.lang.Runnable, java.lang.String) */ public Thread(Runnable target, String name) { init(null, target, name, 0); } /** * Allocates a new <code>Thread</code> object so that it has * <code>target</code> as its run object, has the specified * <code>name</code> as its name, and belongs to the thread group * referred to by <code>group</code>. * <p> * If <code>group</code> is <code>null</code> and there is a * security manager, the group is determined by the security manager's * <code>getThreadGroup</code> method. If <code>group</code> is * <code>null</code> and there is not a security manager, or the * security manager's <code>getThreadGroup</code> method returns * <code>null</code>, the group is set to be the same ThreadGroup * as the thread that is creating the new thread. * * <p>If there is a security manager, its <code>checkAccess</code> * method is called with the ThreadGroup as its argument. * This may result in a SecurityException. * <p> * If the <code>target</code> argument is not <code>null</code>, the * <code>run</code> method of the <code>target</code> is called when * this thread is started. If the target argument is * <code>null</code>, this thread's <code>run</code> method is called * when this thread is started. * <p> * The priority of the newly created thread is set equal to the * priority of the thread creating it, that is, the currently running * thread. The method <code>setPriority</code> may be used to * change the priority to a new value. * <p> * The newly created thread is initially marked as being a daemon * thread if and only if the thread creating it is currently marked * as a daemon thread. The method <code>setDaemon </code> may be used * to change whether or not a thread is a daemon. * * @param group the thread group. * @param target the object whose <code>run</code> method is called. * @param name the name of the new thread. * @exception SecurityException if the current thread cannot create a * thread in the specified thread group. * @see java.lang.Runnable#run() * @see java.lang.Thread#run() * @see java.lang.Thread#setDaemon(boolean) * @see java.lang.Thread#setPriority(int) * @see java.lang.ThreadGroup#checkAccess() * @see SecurityManager#checkAccess */ public Thread(ThreadGroup group, Runnable target, String name) { init(group, target, name, 0); } /** * Allocates a new <code>Thread</code> object so that it has * <code>target</code> as its run object, has the specified * <code>name</code> as its name, belongs to the thread group referred to * by <code>group</code>, and has the specified <i>stack size</i>. * * <p>This constructor is identical to {@link * #Thread(ThreadGroup,Runnable,String)} with the exception of the fact * that it allows the thread stack size to be specified. The stack size * is the approximate number of bytes of address space that the virtual * machine is to allocate for this thread's stack. <b>The effect of the * <tt>stackSize</tt> parameter, if any, is highly platform dependent.</b> * * <p>On some platforms, specifying a higher value for the * <tt>stackSize</tt> parameter may allow a thread to achieve greater * recursion depth before throwing a {@link StackOverflowError}. * Similarly, specifying a lower value may allow a greater number of * threads to exist concurrently without throwing an an {@link * OutOfMemoryError} (or other internal error). The details of * the relationship between the value of the <tt>stackSize</tt> parameter * and the maximum recursion depth and concurrency level are * platform-dependent. <b>On some platforms, the value of the * <tt>stackSize</tt> parameter may have no effect whatsoever.</b> * * <p>The virtual machine is free to treat the <tt>stackSize</tt> * parameter as a suggestion. If the specified value is unreasonably low * for the platform, the virtual machine may instead use some * platform-specific minimum value; if the specified value is unreasonably * high, the virtual machine may instead use some platform-specific * maximum. Likewise, the virtual machine is free to round the specified * value up or down as it sees fit (or to ignore it completely). * * <p>Specifying a value of zero for the <tt>stackSize</tt> parameter will * cause this constructor to behave exactly like the * <tt>Thread(ThreadGroup, Runnable, String)</tt> constructor. * * <p><i>Due to the platform-dependent nature of the behavior of this * constructor, extreme care should be exercised in its use. * The thread stack size necessary to perform a given computation will * likely vary from one JRE implementation to another. In light of this * variation, careful tuning of the stack size parameter may be required, * and the tuning may need to be repeated for each JRE implementation on * which an application is to run.</i> * * <p>Implementation note: Java platform implementers are encouraged to * document their implementation's behavior with respect to the * <tt>stackSize parameter</tt>. * * @param group the thread group. * @param target the object whose <code>run</code> method is called. * @param name the name of the new thread. * @param stackSize the desired stack size for the new thread, or * zero to indicate that this parameter is to be ignored. * @exception SecurityException if the current thread cannot create a * thread in the specified thread group. */ public Thread(ThreadGroup group, Runnable target, String name, long stackSize) { init(group, target, name, stackSize); } /** * Causes this thread to begin execution; the Java Virtual Machine * calls the <code>run</code> method of this thread. * <p> * The result is that two threads are running concurrently: the * current thread (which returns from the call to the * <code>start</code> method) and the other thread (which executes its * <code>run</code> method). * * @exception IllegalThreadStateException if the thread was already * started. * @see java.lang.Thread#run() */ public void start() { synchronized (lock) { if (alive || hasStartedOnce) { throw new IllegalThreadStateException(); } if (!stillborn) { CVM.disableRemoteExceptions(); // Just in case we encounter hidden calls // to wait() boolean unmask = !CVM.maskInterrupts(); try { hasStartedOnce = true; group.add(this); // access to ThreadRegistry is synced in exit(). ThreadRegistry.add(this); // NOTE: start0() will allow the native thread to run. // There's a chance that the thread will finish running // and its exit() method called before start0() returns. // Hence, we should only call start0() after the above // initialization code is done so that there is no race // condition between exit() and this method in setting // these values. // Lock our own critical section so that we do not // need to deal with interrupt() calls in the native // code that waits for the child to start. // This is redundant now that we call // CVM.maskInterrupts() above. synchronized (currentThread().lock) { if (group.saveThreadStarterClassFlag) { threadStarterClass = System.getCallerClass(); } start0(priority); } alive = true; } finally { if (!alive) { try { ThreadRegistry.remove(this); } catch (Throwable t) { } try { group.remove(this); } catch (Throwable t) { } } if (unmask) { CVM.unmaskInterrupts(); } CVM.enableRemoteExceptions(); } } } } private native void start0(int priority); /** * If this thread was constructed using a separate * <code>Runnable</code> run object, then that * <code>Runnable</code> object's <code>run</code> method is called; * otherwise, this method does nothing and returns. * <p> * Subclasses of <code>Thread</code> should override this method. * * @see java.lang.Thread#start() * @see java.lang.Thread#Thread(java.lang.ThreadGroup, * java.lang.Runnable, java.lang.String) * @see java.lang.Runnable#run() */ public void run() { if (target != null) { target.run(); } } /** * This method is called by the system to give a Thread * a chance to clean up before it actually exits. */ private void exit(Throwable t) { // disable any future async/remote exceptions CVM.disableRemoteExceptions(); CVM.maskInterrupts(); stillborn = true; if (group != null) { if (t != null) { try { group.uncaughtException(this, t); } catch (Throwable t0) { // Probably OutOfMemoryError, ignore } } // unlocked reserved resources to prevent // out-of-memory errors setThreadExiting(); try { group.remove(this); } catch (Throwable t0) { // Probably OutOfMemoryError, ignore } group = null; } else { // unlocked reserved resources to prevent // out-of-memory errors setThreadExiting(); } /* Aggressively null object connected to Thread: see bug 4006245 */ target = null; synchronized (lock) { ThreadRegistry.remove(this); eetop = 0; alive = false; lock.notifyAll(); } } /** * This method is called by the system to manage thread * startup and exit. */ private void startup(boolean nativeOverride) { try { try { if (!stillborn && ThreadRegistry.threadCreationAllowed()) { if (nativeOverride) { CVM.setContextArtificial(); runNative(); CVM.postThreadExit(); } else { CVM.setDebugEvents(true); run(); CVM.postThreadExit(); CVM.setDebugEvents(false); } } } finally { // disable any future async/remote exceptions CVM.disableRemoteExceptions(); CVM.maskInterrupts(); stillborn = true; } } catch (Throwable uncaughtException) { exit(uncaughtException); inheritedAccessControlContext = null; return; } exit(null); inheritedAccessControlContext = null; } /** * Used to indicate thread shutdown. */ private static native void setThreadExiting(); private native void runNative(); /** * Forces the thread to stop executing. * <p> * If there is a security manager installed, its <code>checkAccess</code> * method is called with <code>this</code> * as its argument. This may result in a * <code>SecurityException</code> being raised (in the current thread). * <p> * If this thread is different from the current thread (that is, the current * thread is trying to stop a thread other than itself), the * security manager's <code>checkPermission</code> method (with a * <code>RuntimePermission("stopThread")</code> argument) is called in * addition. * Again, this may result in throwing a * <code>SecurityException</code> (in the current thread). * <p> * The thread represented by this thread is forced to stop whatever * it is doing abnormally and to throw a newly created * <code>ThreadDeath</code> object as an exception. * <p> * It is permitted to stop a thread that has not yet been started. * If the thread is eventually started, it immediately terminates. * <p> * An application should not normally try to catch * <code>ThreadDeath</code> unless it must do some extraordinary * cleanup operation (note that the throwing of * <code>ThreadDeath</code> causes <code>finally</code> clauses of * <code>try</code> statements to be executed before the thread * officially dies). If a <code>catch</code> clause catches a * <code>ThreadDeath</code> object, it is important to rethrow the * object so that the thread actually dies. * <p> * The top-level error handler that reacts to otherwise uncaught * exceptions does not print out a message or otherwise notify the * application if the uncaught exception is an instance of * <code>ThreadDeath</code>. * * exception SecurityException if the current thread cannot * modify this thread. * see java.lang.Thread#interrupt() * see java.lang.Thread#checkAccess() * see java.lang.Thread#run() * see java.lang.Thread#start() * see java.lang.ThreadDeath * see java.lang.ThreadGroup#uncaughtException(java.lang.Thread, * java.lang.Throwable) * see SecurityManager#checkAccess(Thread) * see SecurityManager#checkPermission * deprecated This method is inherently unsafe. Stopping a thread with * Thread.stop causes it to unlock all of the monitors that it * has locked (as a natural consequence of the unchecked * <code>ThreadDeath</code> exception propagating up the stack). If * any of the objects previously protected by these monitors were in * an inconsistent state, the damaged objects become visible to * other threads, potentially resulting in arbitrary behavior. Many * uses of <code>stop</code> should be replaced by code that simply * modifies some variable to indicate that the target thread should * stop running. The target thread should check this variable * regularly, and return from its run method in an orderly fashion * if the variable indicates that it is to stop running. If the * target thread waits for long periods (on a condition variable, * for example), the <code>interrupt</code> method should be used to * interrupt the wait. * For more information, see * <a href="{docRoot}/../guide/misc/threadPrimitiveDeprecation.html">Why * are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>. * public final void stop() { stop1(new ThreadDeath(), true); } */ /** * Forces the thread to stop executing. * <p> * If there is a security manager installed, the <code>checkAccess</code> * method of this thread is called, which may result in a * <code>SecurityException</code> being raised (in the current thread). * <p> * If this thread is different from the current thread (that is, the current * thread is trying to stop a thread other than itself) or * <code>obj</code> is not an instance of <code>ThreadDeath</code>, the * security manager's <code>checkPermission</code> method (with the * <code>RuntimePermission("stopThread")</code> argument) is called in * addition. * Again, this may result in throwing a * <code>SecurityException</code> (in the current thread). * <p> * If the argument <code>obj</code> is null, a * <code>NullPointerException</code> is thrown (in the current thread). * <p> * The thread represented by this thread is forced to complete * whatever it is doing abnormally and to throw the * <code>Throwable</code> object <code>obj</code> as an exception. This * is an unusual action to take; normally, the <code>stop</code> method * that takes no arguments should be used. * <p> * It is permitted to stop a thread that has not yet been started. * If the thread is eventually started, it immediately terminates. * * param obj the Throwable object to be thrown. * exception SecurityException if the current thread cannot modify * this thread. * see java.lang.Thread#interrupt() * see java.lang.Thread#checkAccess() * see java.lang.Thread#run() * see java.lang.Thread#start() * see java.lang.Thread#stop() * see SecurityManager#checkAccess(Thread) * see SecurityManager#checkPermission * deprecated This method is inherently unsafe. See {@link #stop} * (with no arguments) for details. An additional danger of this * method is that it may be used to generate exceptions that the * target thread is unprepared to handle (including checked * exceptions that the thread could not possibly throw, were it * not for this method). * For more information, see * <a href="{@docRoot}/../guide/misc/threadPrimitiveDeprecation.html">Why * are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>. * public final void stop(Throwable obj) { stop1(obj, obj instanceof ThreadDeath); } */ /* Only used by deprecated methods private final void stop1(Throwable obj, boolean death) { if (obj == null) { throw new NullPointerException(); } synchronized (lock) { SecurityManager security = System.getSecurityManager(); if (security != null) { checkAccess(); if ((this != Thread.currentThread()) || !death) { if (stopThreadPermission == null) stopThreadPermission = new RuntimePermission("stopThread"); security.checkPermission(stopThreadPermission); } if ((this != Thread.currentThread()) || !death) { if (stopThreadPermission == null) stopThreadPermission = new RuntimePermission("stopThread"); security.checkPermission(stopThreadPermission); } } if (alive && !stillborn) { CVM.throwRemoteException(this, obj); stillborn = death; resume(); // Wake up thread if it was suspended; no-op otherwise } } } */ /** * Interrupts this thread. * * <p> First the {@link #checkAccess() checkAccess} method of this thread * is invoked, which may cause a {@link SecurityException} to be thrown. * * <p> If this thread is blocked in an invocation of the {@link * Object#wait() wait()}, {@link Object#wait(long) wait(long)}, or {@link * Object#wait(long, int) wait(long, int)} methods of the {@link Object} * class, or of the {@link #join()}, {@link #join(long)}, {@link * #join(long, int)}, {@link #sleep(long)}, or {@link #sleep(long, int)}, * methods of this class, then its interrupt status will be cleared and it * will receive an {@link InterruptedException}. * * <p> If none of the previous conditions hold then this thread's interrupt * status will be set. </p> * * @throws SecurityException * if the current thread cannot modify this thread * * @revised 1.4 * @spec JSR-51 */ public void interrupt() { checkAccess(); synchronized (lock) { wasInterrupted = true; interrupt0(); } } /** * Tests whether the current thread has been interrupted. The * <i>interrupted status</i> of the thread is cleared by this method. In * other words, if this method were to be called twice in succession, the * second call would return false (unless the current thread were * interrupted again, after the first call had cleared its interrupted * status and before the second call had examined it). * * @return <code>true</code> if the current thread has been interrupted; * <code>false</code> otherwise. * @see java.lang.Thread#isInterrupted() */ public static boolean interrupted() { Thread self = currentThread(); synchronized (self.lock) { if (self.wasInterrupted) { self.wasInterrupted = false; return self.isInterrupted(true); } } return false; } /** * Tests whether this thread has been interrupted. The <i>interrupted * status</i> of the thread is unaffected by this method. * * @return <code>true</code> if this thread has been interrupted; * <code>false</code> otherwise. * @see java.lang.Thread#interrupted() */ public boolean isInterrupted() { return wasInterrupted && isInterrupted(false); } /** * Tests if some Thread has been interrupted. The interrupted state * is reset or not based on the value of ClearInterrupted that is * passed. */ private native boolean isInterrupted(boolean ClearInterrupted); /** * Destroys this thread, without any cleanup. Any monitors it has * locked remain locked. (This method is not implemented.) */ public void destroy() { throw new NoSuchMethodError(); } /** * Tests if this thread is alive. A thread is alive if it has * been started and has not yet died. * * @return <code>true</code> if this thread is alive; * <code>false</code> otherwise. */ public final boolean isAlive() { synchronized (lock) { return alive; } } /** * Suspends this thread. * <p> * First, the <code>checkAccess</code> method of this thread is called * with no arguments. This may result in throwing a * <code>SecurityException </code>(in the current thread). * <p> * If the thread is alive, it is suspended and makes no further * progress unless and until it is resumed. * * exception SecurityException if the current thread cannot modify * this thread. * see #checkAccess * deprecated This method has been deprecated, as it is * inherently deadlock-prone. If the target thread holds a lock on the * monitor protecting a critical system resource when it is suspended, no * thread can access this resource until the target thread is resumed. If * the thread that would resume the target thread attempts to lock this * monitor prior to calling <code>resume</code>, deadlock results. Such * deadlocks typically manifest themselves as "frozen" processes. * For more information, see * <a href="{docRoot}/../guide/misc/threadPrimitiveDeprecation.html">Why * are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>. * public final void suspend() { checkAccess(); suspend0(); } */ /** * Resumes a suspended thread. * <p> * First, the <code>checkAccess</code> method of this thread is called * with no arguments. This may result in throwing a * <code>SecurityException</code> (in the current thread). * <p> * If the thread is alive but suspended, it is resumed and is * permitted to make progress in its execution. * * exception SecurityException if the current thread cannot modify this * thread. * see #checkAccess * see java.lang.Thread#suspend() * deprecated This method exists solely for use with {@link #suspend}, * which has been deprecated because it is deadlock-prone. * For more information, see * <a href="{docRoot}/../guide/misc/threadPrimitiveDeprecation.html">Why * are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>. * public final void resume() { checkAccess(); resume0(); } */ /** * Changes the priority of this thread. * <p> * First the <code>checkAccess</code> method of this thread is called * with no arguments. This may result in throwing a * <code>SecurityException</code>. * <p> * Otherwise, the priority of this thread is set to the smaller of * the specified <code>newPriority</code> and the maximum permitted * priority of the thread's thread group. * * @param newPriority priority to set this thread to * @exception IllegalArgumentException If the priority is not in the * range <code>MIN_PRIORITY</code> to * <code>MAX_PRIORITY</code>. * @exception SecurityException if the current thread cannot modify * this thread. * @see #getPriority * @see java.lang.Thread#checkAccess() * @see java.lang.Thread#getPriority() * @see java.lang.Thread#getThreadGroup() * @see java.lang.Thread#MAX_PRIORITY * @see java.lang.Thread#MIN_PRIORITY * @see java.lang.ThreadGroup#getMaxPriority() */ public final void setPriority(int newPriority) { checkAccess(); if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) { throw new IllegalArgumentException(); } if (newPriority > group.getMaxPriority()) { newPriority = group.getMaxPriority(); } setPriority0(priority = newPriority); } /** * Returns this thread's priority. * * @return this thread's priority. * @see #setPriority * @see java.lang.Thread#setPriority(int) */ public final int getPriority() { return priority; } /** * Changes the name of this thread to be equal to the argument * <code>name</code>. * <p> * First the <code>checkAccess</code> method of this thread is called * with no arguments. This may result in throwing a * <code>SecurityException</code>. * * @param name the new name for this thread. * @exception SecurityException if the current thread cannot modify this * thread. * @see #getName * @see java.lang.Thread#checkAccess() * @see java.lang.Thread#getName() */ public final void setName(String name) { checkAccess(); this.name = name.toCharArray(); } /** * Returns this thread's name. * * @return this thread's name. * @see #setName * @see java.lang.Thread#setName(java.lang.String) */ public final String getName() { return String.valueOf(name); } /** * Returns the thread group to which this thread belongs. * This method returns null if this thread has died * (been stopped). * * @return this thread's thread group. */ public final ThreadGroup getThreadGroup() { return group; } /** * Returns the number of active threads in the current thread's thread * group. * * @return the number of active threads in the current thread's thread * group. */ public static int activeCount() { return currentThread().getThreadGroup().activeCount(); } /** * Copies into the specified array every active thread in * the current thread's thread group and its subgroups. This method simply * calls the <code>enumerate</code> method of the current thread's thread * group with the array argument. * <p> * First, if there is a security manager, that <code>enumerate</code> * method calls the security * manager's <code>checkAccess</code> method * with the thread group as its argument. This may result * in throwing a <code>SecurityException</code>. * * @param tarray an array of Thread objects to copy to * @return the number of threads put into the array * @exception SecurityException if a security manager exists and its * <code>checkAccess</code> method doesn't allow the operation. * @see java.lang.ThreadGroup#enumerate(java.lang.Thread[]) * @see java.lang.SecurityManager#checkAccess(java.lang.ThreadGroup) */ public static int enumerate(Thread tarray[]) { return currentThread().getThreadGroup().enumerate(tarray); } /** * Counts the number of stack frames in this thread. The thread must * be suspended. * * return the number of stack frames in this thread. * exception IllegalThreadStateException if this thread is not * suspended. * deprecated The definition of this call depends on {@link #suspend}, * which is deprecated. Further, the results of this call * were never well-defined. * public native int countStackFrames(); */ /** * Waits at most <code>millis</code> milliseconds for this thread to * die. A timeout of <code>0</code> means to wait forever. * * @param millis the time to wait in milliseconds. * @exception InterruptedException if another thread has interrupted * the current thread. The <i>interrupted status</i> of the * current thread is cleared when this exception is thrown. */ public final void join(long millis) throws InterruptedException { synchronized (lock) { long base = System.currentTimeMillis(); long now = 0; if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (millis == 0) { while (isAlive()) { lock.wait(0); } } else { while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } lock.wait(delay); now = System.currentTimeMillis() - base; } } } } /** * Waits at most <code>millis</code> milliseconds plus * <code>nanos</code> nanoseconds for this thread to die. * * @param millis the time to wait in milliseconds. * @param nanos 0-999999 additional nanoseconds to wait. * @exception IllegalArgumentException if the value of millis is negative * the value of nanos is not in the range 0-999999. * @exception InterruptedException if another thread has interrupted * the current thread. The <i>interrupted status</i> of the * current thread is cleared when this exception is thrown. */ public final void join(long millis, int nanos) throws InterruptedException { if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (nanos < 0 || nanos > 999999) { throw new IllegalArgumentException( "nanosecond timeout value out of range"); } if (nanos >= 500000 || (nanos != 0 && millis == 0)) { millis++; } join(millis); } /** * Waits for this thread to die. * * @exception InterruptedException if another thread has interrupted * the current thread. The <i>interrupted status</i> of the * current thread is cleared when this exception is thrown. */ public final void join() throws InterruptedException { join(0); } /** * Prints a stack trace of the current thread. This method is used * only for debugging. * * @see java.lang.Throwable#printStackTrace() */ public static void dumpStack() { new Exception("Stack trace").printStackTrace(); } /** * Marks this thread as either a daemon thread or a user thread. The * Java Virtual Machine exits when the only threads running are all * daemon threads. * <p> * This method must be called before the thread is started. * <p> * This method first calls the <code>checkAccess</code> method * of this thread * with no arguments. This may result in throwing a * <code>SecurityException </code>(in the current thread). * <p> * If process model exists, Thread.setDaemon() should be used * as it is defined in J2SE specification. * <p> * If process model does not exist, Thread.setDaemon() should be * used to set threads as daemon threads if the programmer uses * good coding techniques to a) guarantee that the daemon thread will * exit and clean up its resources before either a System.exit() is * called and/or all the user threads have exited, and b) override the * security manager's default behavior to throw SecurityException * when System.exit() is called. * <p> * @param on if <code>true</code>, marks this thread as a * daemon thread. * @exception IllegalThreadStateException if this thread is active. * @exception SecurityException if the current thread cannot modify * this thread. * @see java.lang.Thread#isDaemon() * @see #checkAccess */ public final void setDaemon(boolean on) { checkAccess(); synchronized (lock) { if (alive) { throw new IllegalThreadStateException(); } else { daemon = on; } } } /** * Tests if this thread is a daemon thread. * * @return <code>true</code> if this thread is a daemon thread; * <code>false</code> otherwise. * @see java.lang.Thread#setDaemon(boolean) */ public final boolean isDaemon() { return daemon; } /** * Determines if the currently running thread has permission to * modify this thread. * <p> * If there is a security manager, its <code>checkAccess</code> method * is called with this thread as its argument. This may result in * throwing a <code>SecurityException</code>. * <p> * Note: This method was mistakenly non-final in JDK 1.1. * It has been made final in the Java 2 Platform. * * @exception SecurityException if the current thread is not allowed to * access this thread. * @see java.lang.SecurityManager#checkAccess(java.lang.Thread) */ public final void checkAccess() { SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkAccess(this); } } /** * Returns a string representation of this thread, including the * thread's name, priority, and thread group. * * @return a string representation of this thread. */ public String toString() { ThreadGroup group = getThreadGroup(); if (group != null) { return "Thread[" + getName() + "," + getPriority() + "," + group.getName() + "]"; } else { return "Thread[" + getName() + "," + getPriority() + "," + "" + "]"; } } /** * Returns the context ClassLoader for this Thread. The context * ClassLoader is provided by the creator of the thread for use * by code running in this thread when loading classes and resources. * If not set, the default is the ClassLoader context of the parent * Thread. The context ClassLoader of the primordial thread is * typically set to the class loader used to load the application. * * <p>First, if there is a security manager, and the caller's class * loader is not null and the caller's class loader is not the same as or * an ancestor of the context class loader for the thread whose * context class loader is being requested, then the security manager's * <code>checkPermission</code> * method is called with a * <code>RuntimePermission("getClassLoader")</code> permission * to see if it's ok to get the context ClassLoader.. * * @return the context ClassLoader for this Thread * * @throws SecurityException * if a security manager exists and its * <code>checkPermission</code> method doesn't allow * getting the context ClassLoader. * @see #setContextClassLoader * @see SecurityManager#checkPermission * @see java.lang.RuntimePermission * * @since 1.2 */ public ClassLoader getContextClassLoader() { if (contextClassLoader == null) return null; SecurityManager sm = System.getSecurityManager(); if (sm != null) { ClassLoader ccl = ClassLoader.getCallerClassLoader(); if (ccl != null && ccl != contextClassLoader && !contextClassLoader.isAncestor(ccl)) { sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); } } return contextClassLoader; } /** * Sets the context ClassLoader for this Thread. The context * ClassLoader can be set when a thread is created, and allows * the creator of the thread to provide the appropriate class loader * to code running in the thread when loading classes and resources. * * <p>First, if there is a security manager, its <code>checkPermission</code> * method is called with a * <code>RuntimePermission("setContextClassLoader")</code> permission * to see if it's ok to set the context ClassLoader.. * * @param cl the context ClassLoader for this Thread * * @exception SecurityException if the current thread cannot set the * context ClassLoader. * @see #getContextClassLoader * @see SecurityManager#checkPermission * @see java.lang.RuntimePermission * * @since 1.2 */ public void setContextClassLoader(ClassLoader cl) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(new RuntimePermission("setContextClassLoader")); } contextClassLoader = cl; } /** * Returns <tt>true</tt> if and only if the current thread holds the * monitor lock on the specified object. * * <p>This method is designed to allow a program to assert that * the current thread already holds a specified lock: * <pre> * assert Thread.holdsLock(obj); * </pre> * * @param obj the object on which to test lock ownership * @throws NullPointerException if obj is <tt>null</tt> * @return <tt>true</tt> if the current thread holds the monitor lock on * the specified object. * @since 1.4 */ public static native boolean holdsLock(Object obj); /* Some private helper methods */ private native void setPriority0(int newPriority); /* Only called by deprecated methods private native void suspend0(); private native void resume0(); */ private native void interrupt0(); /* The class that called Thread.start(). */ private Class threadStarterClass; }