Package java.lang

Source Code of java.lang.Thread$UncaughtExceptionHandler

/*
* Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code 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.  Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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 in the LICENSE file that
* accompanied this code).
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

package java.lang;

import java.security.AccessController;
import java.security.AccessControlContext;
import java.security.PrivilegedAction;
import java.util.Map;
import java.util.HashMap;
import java.util.Collections;
import java.util.concurrent.locks.LockSupport;
import sun.nio.ch.Interruptible;
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
*             &nbsp;.&nbsp;.&nbsp;.
*         }
*     }
* </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
*             &nbsp;.&nbsp;.&nbsp;.
*         }
*     }
* </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
* @see     Runnable
* @see     Runtime#exit(int)
* @see     #run()
* @see     #stop()
* @since   JDK1.0
*/
public
class Thread implements Runnable {
    // [IKVM]
    final class Cleanup {
        private final Thread thread;

        Cleanup(Thread thread) {
            this.thread = thread;
        }

        protected void finalize() {
            thread.die();
        }
    }
    /* --- start IKVM specific state --- */
    static final int[] nonDaemonCount = new int[1];
    @cli.System.ThreadStaticAttribute.Annotation
    static Thread current;
    @cli.System.ThreadStaticAttribute.Annotation
    private static Cleanup cleanup;
    private final Object lock = new Object();
    private cli.System.Threading.Thread nativeThread;
    private Throwable stillborn;
    private boolean running;    // used only for coordination with stop0(), is never set to false
    private boolean interruptPending;
    private volatile boolean nativeInterruptPending;
    private volatile boolean interruptableWait;
    private boolean timedWait;
    volatile Object parkLock;   // used by get/setParkLock in map.xml
    int parkState;              // used by cmpxchgParkState in map.xml
    /* --- end IKVM specific state --- */

    private char        name[];
    private int         priority;
    private Thread      threadQ;
    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;

    /* 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 */
    AccessController.LazyContext lazyInheritedAccessControlContext;

    /* For autonumbering anonymous threads. */
    private static int threadInitNumber;
    private static synchronized int nextThreadNum() {
        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;

    /*
     * JVM-private state that persists after native thread termination.
     */
    private long nativeParkEventPointer;

    /*
     * Thread ID
     */
    private long tid;

    /* For generating thread ID */
    private static long threadSeqNumber;

    /* Java thread status for tools,
     * initialized to indicate thread 'not yet started'
     */

    private volatile int threadStatus = 0;

    private static synchronized long nextThreadID() {
        return ++threadSeqNumber;
    }

    /**
     * The argument supplied to the current call to
     * java.util.concurrent.locks.LockSupport.park.
     * Set by (private) java.util.concurrent.locks.LockSupport.setBlocker
     * Accessed using java.util.concurrent.locks.LockSupport.getBlocker
     */
    volatile Object parkBlocker;

    /* The object in which this thread is blocked in an interruptible I/O
     * operation, if any.  The blocker's interrupt method should be invoked
     * after setting this thread's interrupt status.
     */
    private volatile Interruptible blocker;
    private Object blockerLock = new Object();

    /* Set the blocker field; invoked via sun.misc.SharedSecrets from java.nio code
     */
    void blockedOn(Interruptible b) {
        synchronized (blockerLock) {
            blocker = b;
        }
    }

    /**
     * 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;

    /* If stop was called before start */
    private boolean stopBeforeStart;

    /* Remembered Throwable from stop before start */
    private Throwable throwableFromStop;

    /* Whether or not the Thread has been completely constructed;
     * init or clone method has successfully completed */
    private volatile Thread me;    // null

    /**
     * Returns a reference to the currently executing thread object.
     *
     * @return  the currently executing thread.
     */
    public static Thread currentThread() {
        Thread c = current;
        if (c == null) {
            c = new Thread(getMainThreadGroup());
        }
        return c;
    }
   
    private static native ThreadGroup getMainThreadGroup();

    /**
     * Causes the currently executing thread object to temporarily pause
     * and allow other threads to execute.
     */
    public static void yield() {
        cli.System.Threading.Thread.Sleep(0);
    }
   
    private void enterInterruptableWait(boolean timedWait) throws InterruptedException {
        synchronized (lock) {
            if (interruptPending) {
                interruptPending = false;
                throw new InterruptedException();
            }
            interruptableWait = true;
            this.timedWait = timedWait;
        }
    }
   
    private void leaveInterruptableWait() throws InterruptedException {
        cli.System.Threading.ThreadInterruptedException dotnetInterrupt = null;
        interruptableWait = false;
        for (; ; ) {
            try {
                if (false) throw new cli.System.Threading.ThreadInterruptedException();
                synchronized (lock) {
                    if (nativeInterruptPending) {
                        nativeInterruptPending = false;
                        // HACK if there is a pending Interrupt (on the .NET thread), we need to consume that
                        // (if there was no contention on "lock (this)" above the interrupted state isn't checked)
                        try {
                            if (false) throw new cli.System.Threading.ThreadInterruptedException();
                            cli.System.Threading.Thread t = cli.System.Threading.Thread.get_CurrentThread();
                            // the obvious thing to do would be t.Interrupt() / t.Join(),
                            // but for some reason that causes a regression in JSR166TestCase (probably a CLR bug)
                            // so we waste a time slice... sigh.
                            t.Join(1);
                        }
                        catch (cli.System.Threading.ThreadInterruptedException _) {
                        }
                    }
                    if (interruptPending) {
                        interruptPending = false;
                        throw new InterruptedException();
                    }
                }
                break;
            }
            catch (cli.System.Threading.ThreadInterruptedException x) {
                dotnetInterrupt = x;
                nativeInterruptPending = false;
            }
        }
        if (dotnetInterrupt != null) {
            ikvm.runtime.Util.throwException(dotnetInterrupt);
        }
    }

    /**
     * Causes the currently executing thread to sleep (temporarily cease
     * execution) for the specified number of milliseconds, subject to
     * the precision and accuracy of system timers and schedulers. The thread
     * does not lose ownership of any monitors.
     *
     * @param      millis   the length of time to sleep in milliseconds.
     * @exception  InterruptedException if any thread has interrupted
     *             the current thread.  The <i>interrupted status</i> of the
     *             current thread is cleared when this exception is thrown.
     * @see        Object#notify()
     */
    public static void sleep(long millis) throws InterruptedException {
        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }
        Thread c = currentThread();
        c.enterInterruptableWait(true);
        try {
            if (false) throw new cli.System.Threading.ThreadInterruptedException();
            for (long iter = millis / Integer.MAX_VALUE; iter != 0; iter--)
            {
                cli.System.Threading.Thread.Sleep(Integer.MAX_VALUE);
            }
            cli.System.Threading.Thread.Sleep((int)(millis % Integer.MAX_VALUE));
        }
        catch (cli.System.Threading.ThreadInterruptedException _) {
        }
        finally {
            c.leaveInterruptableWait();
        }
    }

    /**
     * Causes the currently executing thread to sleep (cease execution)
     * for the specified number of milliseconds plus the specified number
     * of nanoseconds, subject to the precision and accuracy of system
     * timers and schedulers. 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 any thread has interrupted
     *             the current thread.  The <i>interrupted status</i> of the
     *             current thread is cleared when this exception is thrown.
     * @see        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++;
        }

        sleep(millis);
    }

    /**
     * Initializes 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) {
        Thread parent = currentThread();
        SecurityManager security = System.getSecurityManager();
        if (g == null) {
            /* Determine if it's an applet or not */

            /* 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();

        /*
         * Do we have the required permissions?
         */
        if (security != null) {
            if (isCCLOverridden(this)) {
                security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
            }
        }


        g.addUnstarted();

        this.group = g;
        this.daemon = parent.isDaemon();
        this.priority = parent.getPriority();
        this.name = name.toCharArray();
        if (isCCLOverridden(parent))
            this.contextClassLoader = parent.getContextClassLoader();
        else
            this.contextClassLoader = parent.contextClassLoader;
        this.lazyInheritedAccessControlContext = AccessController.getLazyContext(parent.lazyInheritedAccessControlContext);
        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;

        /* Set thread ID */
        tid = nextThreadID();

        this.me = this;
    }
   
    // [IKVM] constructor for attaching to a .NET thread
    Thread(ThreadGroup g) {
        this.running = true;
        cli.System.Threading.Thread thread = cli.System.Threading.Thread.get_CurrentThread();
        nativeThread = thread;
        String name = thread.get_Name();
        if (name == null) {
            name = "Thread-" + nextThreadNum();
        }

        this.group = g;
        this.daemon = thread.get_IsBackground();
        this.priority = mapClrPriorityToJava(thread.get_Priority().Value);
        this.name = name.toCharArray();
        this.contextClassLoader = ClassLoader.DUMMY;
        this.threadStatus = 0x0005; /* JVMTI_THREAD_STATE_ALIVE + JVMTI_THREAD_STATE_RUNNABLE */

        /* Set thread ID */
        tid = nextThreadID();

        synchronized (g) {
            g.addUnstarted();
            g.add(this);
        }

        current = this;
        cleanup = new Cleanup(this);

        if (!daemon) {
            cli.System.Threading.Interlocked.Increment(nonDaemonCount);
        }

        this.me = this;
    }
   
    private static int mapClrPriorityToJava(int priority) {
        // TODO consider supporting -XX:JavaPriorityX_To_OSPriority settings
        switch (priority) {
        case cli.System.Threading.ThreadPriority.Lowest:
            return MIN_PRIORITY;
        case cli.System.Threading.ThreadPriority.BelowNormal:
            return 3;
        default:
        case cli.System.Threading.ThreadPriority.Normal:
            return NORM_PRIORITY;
        case cli.System.Threading.ThreadPriority.AboveNormal:
            return 7;
        case cli.System.Threading.ThreadPriority.Highest:
            return MAX_PRIORITY;
        }
    }
   
    private static int mapJavaPriorityToClr(int priority) {
        // TODO consider supporting -XX:JavaPriorityX_To_OSPriority settings
        if (priority == MIN_PRIORITY) {
            return cli.System.Threading.ThreadPriority.Lowest;
        }
        else if (priority > Thread.MIN_PRIORITY && priority < Thread.NORM_PRIORITY) {
            return cli.System.Threading.ThreadPriority.BelowNormal;
        }
        else if (priority == Thread.NORM_PRIORITY) {
            return cli.System.Threading.ThreadPriority.Normal;
        }
        else if (priority > Thread.NORM_PRIORITY && priority < Thread.MAX_PRIORITY) {
            return cli.System.Threading.ThreadPriority.AboveNormal;
        }
        else if (priority == Thread.MAX_PRIORITY) {
            return cli.System.Threading.ThreadPriority.Highest;
        }
        else {
            // can't happen
            return cli.System.Threading.ThreadPriority.Normal;
        }
    }

    /**
     * Returns a clone if the class of this object is {@link Cloneable Cloneable}.
     *
     * @return  a clone if the class of this object is {@code Cloneable}
     *
     * @throws  CloneNotSupportedException
     *          if this method is invoked on a class that does not
     *          support {@code Cloneable}
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Thread t;
        synchronized(this) {
            t = (Thread) super.clone();

            t.tid = nextThreadID();
            t.parkBlocker = null;
            t.blocker = null;
            t.blockerLock = new Object();
            t.threadLocals = null;

            group.checkAccess();
            if (threadStatus == 0) {
                group.addUnstarted();
            }
            t.setPriority(priority);

            final Thread current = Thread.currentThread();
            if (current.inheritableThreadLocals != null)
                t.inheritableThreadLocals =
                    ThreadLocal.createInheritedMap(current.inheritableThreadLocals);
        }

        t.me = t;
        return t;
    }

    /**
     * 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     #Thread(ThreadGroup, Runnable, 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     #Thread(ThreadGroup, Runnable, 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        #Thread(ThreadGroup, Runnable, 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     #Thread(ThreadGroup, Runnable, 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        #Thread(ThreadGroup, Runnable, String)
     */
    public Thread(ThreadGroup group, String name) {
        init(group, null, name, 0);
    }

    /**
     * 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     #Thread(ThreadGroup, Runnable, 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.
     * <p>In addition, its <code>checkPermission</code>
     * method is called with the
     * <code>RuntimePermission("enableContextClassLoaderOverride")</code>
     * permission when invoked directly or indirectly by the constructor
     * of a subclass which overrides the <code>getContextClassLoader</code>
     * or <code>setContextClassLoader</code> methods.
     * 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 or cannot
     *               override the context class loader methods.
     * @see        Runnable#run()
     * @see        #run()
     * @see        #setDaemon(boolean)
     * @see        #setPriority(int)
     * @see        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 {@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.
     * @since 1.4
     */
    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).
     * <p>
     * It is never legal to start a thread more than once.
     * In particular, a thread may not be restarted once it has completed
     * execution.
     *
     * @exception  IllegalThreadStateException  if the thread was already
     *               started.
     * @see        #run()
     * @see        #stop()
     */
    public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0 || this != me)
            throw new IllegalThreadStateException();
        group.add(this);
        start0();
        if (stopBeforeStart) {
            stop0(throwableFromStop);
        }
    }

    private void start0() {
        cli.System.Threading.ThreadStart threadStart = new cli.System.Threading.ThreadStart(new cli.System.Threading.ThreadStart.Method() {
            @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation
            public void Invoke() {
                threadProc();
            }
        });
        if (stackSize <= 0) {
            nativeThread = new cli.System.Threading.Thread(threadStart);
        }
        else {
            int maxStackSize = (int)Math.min(Math.max(128 * 1024, stackSize), Integer.MAX_VALUE);
            nativeThread = new cli.System.Threading.Thread(threadStart, maxStackSize);
        }
        nativeThread.set_Name(getName());
        nativeThread.set_IsBackground(daemon);
        nativeThread.set_Priority(cli.System.Threading.ThreadPriority.wrap(mapJavaPriorityToClr(priority)));
        String apartment = Props.props.getProperty("ikvm.apartmentstate", "").toLowerCase();
        if ("mta".equals(apartment)) {
            nativeThread.SetApartmentState(cli.System.Threading.ApartmentState.wrap(cli.System.Threading.ApartmentState.MTA));
        }
        else if ("sta".equals(apartment)) {
            nativeThread.SetApartmentState(cli.System.Threading.ApartmentState.wrap(cli.System.Threading.ApartmentState.STA));
        }
        threadStatus = 0x0005; // JVMTI_THREAD_STATE_ALIVE + JVMTI_THREAD_STATE_RUNNABLE
        nativeThread.Start();
        if (!daemon) {
            cli.System.Threading.Interlocked.Increment(nonDaemonCount);
        }
    }

    /**
     * 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     #start()
     * @see     #stop()
     * @see     #Thread(ThreadGroup, Runnable, String)
     */
    public void run() {
        if (target != null) {
            target.run();
        }
    }
   
    // [IKVM] for threads started from Java, this method is called on the thread itself,
    // but for .NET threads it will be called by the finalizer of the Cleanup object.
    // NOTE there might be a race condition here (when the thread's Cleanup object
    // is finalized during AppDomain shutdown while the thread is also exiting on its own),
    // but that doesn't matter because Thread.exit() is safe to call multiple times.
    void die() {
        exit();
        synchronized (lock) {
            nativeThread = null;
            threadStatus = 0x0002; // JVMTI_THREAD_STATE_TERMINATED
        }
        wakeupJoinedThreads();
        if (!daemon) {
            // TODO there is a race condition in the non-daemon counting
            // (setDaemon() isn't synchronized so it may clear/set the daemon flag without the count being affected)
            cli.System.Threading.Interlocked.Decrement(nonDaemonCount);
        }
        if (current == this) {
            current = null;
            // check if we have a cleanup object, this happens if we attach and subsequently detach from JNI code
            if (cleanup != null) {
                cli.System.GC.SuppressFinalize(cleanup);
                cleanup = null;
            }
        }
    }

    private void wakeupJoinedThreads() {
        // HACK locking this here isn't ideal, because we might be invoked from
        // the Cleanup object's finalizer and some user code might own the lock and hence
        // block the finalizer thread.
        // A second scenario is that another thread is currently blocking inside stop()
        // (the Thread.Abort() call will block while we are running the finally block)
        // and that thread will own the lock on our thread object.
        boolean locked = false;
        try {
            locked = cli.System.Threading.Monitor.TryEnter(this);
            if (locked) {
                notifyAll();
            } else {
                // HACK schedule an asynchronous notification
                cli.System.Threading.ThreadPool.QueueUserWorkItem(
                    new cli.System.Threading.WaitCallback(
                        new cli.System.Threading.WaitCallback.Method() {
                            public void Invoke(Object thread) {
                                synchronized (thread) {
                                    thread.notifyAll();
                                }
                            }
                        }), this);
            }
        }
        finally {
            if (locked)
                cli.System.Threading.Monitor.Exit(this);
        }
    }

    /**
     * This method is called by the system to give a Thread
     * a chance to clean up before it actually exits.
     */
    private void exit() {
        if (group != null) {
            group.remove(this);
            group = null;
        }
        /* Aggressively null out all reference fields: see bug 4006245 */
        target = null;
        /* Speed the release of some of these resources */
        threadLocals = null;
        inheritableThreadLocals = null;
        lazyInheritedAccessControlContext = null;
        blocker = null;
        uncaughtExceptionHandler = null;
    }

    /**
     * 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        #interrupt()
     * @see        #checkAccess()
     * @see        #run()
     * @see        #start()
     * @see        ThreadDeath
     * @see        ThreadGroup#uncaughtException(Thread,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}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
     *       are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
     */
    @Deprecated
    public final void stop() {
        // If the thread is already dead, return.
        // A zero status value corresponds to "NEW".
        if ((threadStatus != 0) && !isAlive()) {
            return;
        }
        stop1(new ThreadDeath());
    }

    /**
     * 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 stop
     * 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.
     * @throws     NullPointerException if obj is <tt>null</tt>.
     * @see        #interrupt()
     * @see        #checkAccess()
     * @see        #run()
     * @see        #start()
     * @see        #stop()
     * @see        SecurityManager#checkAccess(Thread)
     * @see        SecurityManager#checkPermission
     * @deprecated This method is inherently unsafe.  See {@link #stop()}
     *        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}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
     *        are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
     */
    @Deprecated
    public final synchronized void stop(Throwable obj) {
        stop1(obj);
    }

    /**
     * Common impl for stop() and stop(Throwable).
     */
    private final synchronized void stop1(Throwable th) {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            checkAccess();
            if ((this != Thread.currentThread()) ||
                (!(th instanceof ThreadDeath))) {
                security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
            }
        }
        // A zero status value corresponds to "NEW"
        if (threadStatus != 0) {
            resume(); // Wake up thread if it was suspended; no-op otherwise
            stop0(th);
        } else {

            // Must do the null arg check that the VM would do with stop0
            if (th == null) {
                throw new NullPointerException();
            }

            // Remember this stop attempt for if/when start is used
            stopBeforeStart = true;
            throwableFromStop = th;
        }
    }

    /**
     * Interrupts this thread.
     *
     * <p> Unless the current thread is interrupting itself, which is
     * always permitted, 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 this thread is blocked in an I/O operation upon an {@link
     * java.nio.channels.InterruptibleChannel </code>interruptible
     * channel<code>} then the channel will be closed, the thread's interrupt
     * status will be set, and the thread will receive a {@link
     * java.nio.channels.ClosedByInterruptException}.
     *
     * <p> If this thread is blocked in a {@link java.nio.channels.Selector}
     * then the thread's interrupt status will be set and it will return
     * immediately from the selection operation, possibly with a non-zero
     * value, just as if the selector's {@link
     * java.nio.channels.Selector#wakeup wakeup} method were invoked.
     *
     * <p> If none of the previous conditions hold then this thread's interrupt
     * status will be set. </p>
     *
     * <p> Interrupting a thread that is not alive need not have any effect.
     *
     * @throws  SecurityException
     *          if the current thread cannot modify this thread
     *
     * @revised 6.0
     * @spec JSR-51
     */
    public void interrupt() {
        if (this != Thread.currentThread())
            checkAccess();

        synchronized (blockerLock) {
            Interruptible b = blocker;
            if (b != null) {
                interrupt0();           // Just to set the interrupt flag
                b.interrupt();
                return;
            }
        }
        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).
     *
     * <p>A thread interruption ignored because a thread was not alive
     * at the time of the interrupt will be reflected by this method
     * returning false.
     *
     * @return  <code>true</code> if the current thread has been interrupted;
     *          <code>false</code> otherwise.
     * @see #isInterrupted()
     * @revised 6.0
     */
    public static boolean interrupted() {
        return currentThread().isInterrupted(true);
    }

    /**
     * Tests whether this thread has been interrupted.  The <i>interrupted
     * status</i> of the thread is unaffected by this method.
     *
     * <p>A thread interruption ignored because a thread was not alive
     * at the time of the interrupt will be reflected by this method
     * returning false.
     *
     * @return  <code>true</code> if this thread has been interrupted;
     *          <code>false</code> otherwise.
     * @see     #interrupted()
     * @revised 6.0
     */
    public boolean isInterrupted() {
        return 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 boolean isInterrupted(boolean ClearInterrupted) {
        synchronized (lock) {
            boolean b = interruptPending;
            if (ClearInterrupted) {
                interruptPending = false;
            }
            return b;
        }
    }

    /**
     * Throws {@link NoSuchMethodError}.
     *
     * @deprecated This method was originally designed to destroy this
     *     thread without any cleanup. Any monitors it held would have
     *     remained locked. However, the method was never implemented.
     *     If if were to be implemented, it would be deadlock-prone in
     *     much the manner of {@link #suspend}. If the target thread held
     *     a lock protecting a critical system resource when it was
     *     destroyed, no thread could ever access this resource again.
     *     If another thread ever attempted to lock this resource, deadlock
     *     would result. Such deadlocks typically manifest themselves as
     *     "frozen" processes. For more information, see
     *     <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">
     *     Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
     * @throws NoSuchMethodError always
     */
    @Deprecated
    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() {
        return (threadStatus & 0x0001) != 0;
    }

    /**
     * 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}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
     *   are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
     */
    @Deprecated
    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        #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}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
     *     are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
     */
    @Deprecated
    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        #checkAccess()
     * @see        #getThreadGroup()
     * @see        #MAX_PRIORITY
     * @see        #MIN_PRIORITY
     * @see        ThreadGroup#getMaxPriority()
     */
    public final void setPriority(int newPriority) {
        ThreadGroup g;
        checkAccess();
        if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
            throw new IllegalArgumentException();
        }
        if((g = getThreadGroup()) != null) {
            if (newPriority > g.getMaxPriority()) {
                newPriority = g.getMaxPriority();
            }
            setPriority0(priority = newPriority);
        }
    }

    /**
     * Returns this thread's priority.
     *
     * @return  this thread's priority.
     * @see     #setPriority
     */
    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        #checkAccess()
     */
    public final void setName(String name) {
        checkAccess();
        this.name = name.toCharArray();
    }

    /**
     * Returns this thread's name.
     *
     * @return  this thread's name.
     * @see     #setName(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     ThreadGroup#enumerate(Thread[])
     * @see     SecurityManager#checkAccess(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.
     */
    @Deprecated
    public int countStackFrames() {
        return 0;
    }

    /**
     * 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 any thread has interrupted
     *             the current thread.  The <i>interrupted status</i> of the
     *             current thread is cleared when this exception is thrown.
     */
    public final synchronized void join(long millis)
    throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (millis == 0) {
            while (isAlive()) {
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                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 any thread has interrupted
     *             the current thread.  The <i>interrupted status</i> of the
     *             current thread is cleared when this exception is thrown.
     */
    public final synchronized 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 any 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 to the standard error stream.
     * This method is used only for debugging.
     *
     * @see     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).
    *
     * @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        #isDaemon()
     * @see        #checkAccess
     */
    public final void setDaemon(boolean on) {
        checkAccess();
        if (isAlive()) {
            throw new IllegalThreadStateException();
        }
        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     #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>.
     *
     * @exception  SecurityException  if the current thread is not allowed to
     *               access this thread.
     * @see        SecurityManager#checkAccess(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 RuntimePermission
     *
     * @since 1.2
     */
    public ClassLoader getContextClassLoader() {
        if (contextClassLoader == ClassLoader.DUMMY) {
            contextClassLoader = ClassLoader.getSystemClassLoader();
        }
        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 RuntimePermission
     *
     * @since 1.2
     */
    public void setContextClassLoader(ClassLoader cl) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(new RuntimePermission("setContextClassLoader"));
        }
        contextClassLoader = cl;
    }
   
    // [IKVM] called by sun.misc.Launcher to initialize the context class loader
    @ikvm.lang.Internal
    public void initContextClassLoader(ClassLoader cl) {
        // we only set contextClassLoader if it hasn't been set (by user code) previously
        if (contextClassLoader == ClassLoader.DUMMY) {
            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 boolean holdsLock(Object obj) {
        if (obj == null) {
            throw new NullPointerException();
        }
        try {
            if (false) throw new cli.System.Threading.SynchronizationLockException();
            // The 1.5 memory model (JSR133) explicitly allows spurious wake-ups from Object.wait,
            // so we abuse Pulse to check if we own the monitor.
            cli.System.Threading.Monitor.Pulse(obj);
            return true;
        }
        catch (cli.System.Threading.SynchronizationLockException _) {
            return false;
        }
    }

    private static final StackTraceElement[] EMPTY_STACK_TRACE
        = new StackTraceElement[0];

    /**
     * Returns an array of stack trace elements representing the stack dump
     * of this thread.  This method will return a zero-length array if
     * this thread has not started or has terminated.
     * If the returned array is of non-zero length then the first element of
     * the array represents the top of the stack, which is the most recent
     * method invocation in the sequence.  The last element of the array
     * represents the bottom of the stack, which is the least recent method
     * invocation in the sequence.
     *
     * <p>If there is a security manager, and this thread is not
     * the current thread, then the security manager's
     * <tt>checkPermission</tt> method is called with a
     * <tt>RuntimePermission("getStackTrace")</tt> permission
     * to see if it's ok to get the stack trace.
     *
     * <p>Some virtual machines may, under some circumstances, omit one
     * or more stack frames from the stack trace.  In the extreme case,
     * a virtual machine that has no stack trace information concerning
     * this thread is permitted to return a zero-length array from this
     * method.
     *
     * @return an array of <tt>StackTraceElement</tt>,
     * each represents one stack frame.
     *
     * @throws SecurityException
     *        if a security manager exists and its
     *        <tt>checkPermission</tt> method doesn't allow
     *        getting the stack trace of thread.
     * @see SecurityManager#checkPermission
     * @see RuntimePermission
     * @see Throwable#getStackTrace
     *
     * @since 1.5
     */
    public StackTraceElement[] getStackTrace() {
        if (this != Thread.currentThread()) {
            // check for getStackTrace permission
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                security.checkPermission(
                    SecurityConstants.GET_STACK_TRACE_PERMISSION);
            }
            // optimization so we do not call into the vm for threads that
            // have not yet started or have terminated
            if (!isAlive()) {
                return EMPTY_STACK_TRACE;
            }
            StackTraceElement[][] stackTraceArray = dumpThreads(new Thread[] {this});
            StackTraceElement[] stackTrace = stackTraceArray[0];
            // a thread that was alive during the previous isAlive call may have
            // since terminated, therefore not having a stacktrace.
            if (stackTrace == null) {
                stackTrace = EMPTY_STACK_TRACE;
            }
            return stackTrace;
        } else {
            // Don't need JVM help for current thread
            return (new Exception()).getStackTrace();
        }
    }

    /**
     * Returns a map of stack traces for all live threads.
     * The map keys are threads and each map value is an array of
     * <tt>StackTraceElement</tt> that represents the stack dump
     * of the corresponding <tt>Thread</tt>.
     * The returned stack traces are in the format specified for
     * the {@link #getStackTrace getStackTrace} method.
     *
     * <p>The threads may be executing while this method is called.
     * The stack trace of each thread only represents a snapshot and
     * each stack trace may be obtained at different time.  A zero-length
     * array will be returned in the map value if the virtual machine has
     * no stack trace information about a thread.
     *
     * <p>If there is a security manager, then the security manager's
     * <tt>checkPermission</tt> method is called with a
     * <tt>RuntimePermission("getStackTrace")</tt> permission as well as
     * <tt>RuntimePermission("modifyThreadGroup")</tt> permission
     * to see if it is ok to get the stack trace of all threads.
     *
     * @return a <tt>Map</tt> from <tt>Thread</tt> to an array of
     * <tt>StackTraceElement</tt> that represents the stack trace of
     * the corresponding thread.
     *
     * @throws SecurityException
     *        if a security manager exists and its
     *        <tt>checkPermission</tt> method doesn't allow
     *        getting the stack trace of thread.
     * @see #getStackTrace
     * @see SecurityManager#checkPermission
     * @see RuntimePermission
     * @see Throwable#getStackTrace
     *
     * @since 1.5
     */
    public static Map<Thread, StackTraceElement[]> getAllStackTraces() {
        // check for getStackTrace permission
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkPermission(
                SecurityConstants.GET_STACK_TRACE_PERMISSION);
            security.checkPermission(
                SecurityConstants.MODIFY_THREADGROUP_PERMISSION);
        }

        // Get a snapshot of the list of all threads
        Thread[] threads = getThreads();
        StackTraceElement[][] traces = dumpThreads(threads);
        Map<Thread, StackTraceElement[]> m
            = new HashMap<Thread, StackTraceElement[]>(threads.length);
        for (int i = 0; i < threads.length; i++) {
            StackTraceElement[] stackTrace = traces[i];
            if (stackTrace != null) {
                m.put(threads[i], stackTrace);
            }
            // else terminated so we don't put it in the map
        }
        return m;
    }


    private static final RuntimePermission SUBCLASS_IMPLEMENTATION_PERMISSION =
                    new RuntimePermission("enableContextClassLoaderOverride");

    /**
     * Verifies that this (possibly subclass) instance can be constructed
     * without violating security constraints: the subclass must not override
     * security-sensitive non-final methods, or else the
     * "enableContextClassLoaderOverride" RuntimePermission is checked.
     */
    private static native boolean isCCLOverridden(Thread thread); // [IKVM] implemented in map.xml

    private static StackTraceElement[][] dumpThreads(Thread[] threads) {
        StackTraceElement[][] stacks = new StackTraceElement[threads.length][];
        for (int i = 0; i < threads.length; i++) {
            cli.System.Threading.Thread nativeThread = threads[i].nativeThread;
            if (nativeThread == null) {
                stacks[i] = new StackTraceElement[0];
            } else {
                try {
                    if (false) throw new cli.System.Threading.ThreadStateException();
                    boolean suspended = false;
                    if ((nativeThread.get_ThreadState().Value & cli.System.Threading.ThreadState.Suspended) == 0 && nativeThread != cli.System.Threading.Thread.get_CurrentThread()) {
                        suspended = true;
                        nativeThread.Suspend();
                    }
                    cli.System.Diagnostics.StackTrace stack;
                    try {
                        stack = new cli.System.Diagnostics.StackTrace(nativeThread, true);
                    }
                    finally {
                        if (suspended) {
                            nativeThread.Resume();
                        }
                    }
                    stacks[i] = getStackTrace(stack);
                }
                catch (cli.System.Threading.ThreadStateException _) {
                    stacks[i] = new StackTraceElement[0];
                }
            }
        }
        return stacks;
    }
   
    private static native StackTraceElement[] getStackTrace(cli.System.Diagnostics.StackTrace stack);

    private static Thread[] getThreads() {
        return (Thread[])AccessController.doPrivileged(
            new PrivilegedAction() {
                public Object run() {
                    ThreadGroup root = getMainThreadGroup();
                    for (; ; ) {
                        Thread[] threads = new Thread[root.activeCount()];
                        if (root.enumerate(threads) == threads.length) {
                            return threads;
                        }
                    }
                }
            });
    }

    /**
     * Returns the identifier of this Thread.  The thread ID is a positive
     * <tt>long</tt> number generated when this thread was created.
     * The thread ID is unique and remains unchanged during its lifetime.
     * When a thread is terminated, this thread ID may be reused.
     *
     * @return this thread's ID.
     * @since 1.5
     */
    public long getId() {
        return tid;
    }

    /**
     * A thread state.  A thread can be in one of the following states:
     * <ul>
     * <li>{@link #NEW}<br>
     *     A thread that has not yet started is in this state.
     *     </li>
     * <li>{@link #RUNNABLE}<br>
     *     A thread executing in the Java virtual machine is in this state.
     *     </li>
     * <li>{@link #BLOCKED}<br>
     *     A thread that is blocked waiting for a monitor lock
     *     is in this state.
     *     </li>
     * <li>{@link #WAITING}<br>
     *     A thread that is waiting indefinitely for another thread to
     *     perform a particular action is in this state.
     *     </li>
     * <li>{@link #TIMED_WAITING}<br>
     *     A thread that is waiting for another thread to perform an action
     *     for up to a specified waiting time is in this state.
     *     </li>
     * <li>{@link #TERMINATED}<br>
     *     A thread that has exited is in this state.
     *     </li>
     * </ul>
     *
     * <p>
     * A thread can be in only one state at a given point in time.
     * These states are virtual machine states which do not reflect
     * any operating system thread states.
     *
     * @since   1.5
     * @see #getState
     */
    public enum State {
        /**
         * Thread state for a thread which has not yet started.
         */
        NEW,

        /**
         * Thread state for a runnable thread.  A thread in the runnable
         * state is executing in the Java virtual machine but it may
         * be waiting for other resources from the operating system
         * such as processor.
         */
        RUNNABLE,

        /**
         * Thread state for a thread blocked waiting for a monitor lock.
         * A thread in the blocked state is waiting for a monitor lock
         * to enter a synchronized block/method or
         * reenter a synchronized block/method after calling
         * {@link Object#wait() Object.wait}.
         */
        BLOCKED,

        /**
         * Thread state for a waiting thread.
         * A thread is in the waiting state due to calling one of the
         * following methods:
         * <ul>
         *   <li>{@link Object#wait() Object.wait} with no timeout</li>
         *   <li>{@link #join() Thread.join} with no timeout</li>
         *   <li>{@link LockSupport#park() LockSupport.park}</li>
         * </ul>
         *
         * <p>A thread in the waiting state is waiting for another thread to
         * perform a particular action.
         *
         * For example, a thread that has called <tt>Object.wait()</tt>
         * on an object is waiting for another thread to call
         * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
         * that object. A thread that has called <tt>Thread.join()</tt>
         * is waiting for a specified thread to terminate.
         */
        WAITING,

        /**
         * Thread state for a waiting thread with a specified waiting time.
         * A thread is in the timed waiting state due to calling one of
         * the following methods with a specified positive waiting time:
         * <ul>
         *   <li>{@link #sleep Thread.sleep}</li>
         *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
         *   <li>{@link #join(long) Thread.join} with timeout</li>
         *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
         *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
         * </ul>
         */
        TIMED_WAITING,

        /**
         * Thread state for a terminated thread.
         * The thread has completed execution.
         */
        TERMINATED;
    }

    /**
     * Returns the state of this thread.
     * This method is designed for use in monitoring of the system state,
     * not for synchronization control.
     *
     * @return this thread's state.
     * @since 1.5
     */
    public State getState() {
        // get current thread state
        switch (threadStatus) {
            case 0:
                return State.NEW;
            case 0x0002:
                return State.TERMINATED;
        }
        synchronized (lock) {
            if (interruptableWait) {
                // NOTE if objectWait has satisfied the wait condition (or has been interrupted or has timed-out),
                // it can be blocking on the re-acquire of the monitor, but we have no way of detecting that.
                return timedWait ? State.TIMED_WAITING : State.WAITING;
            }
        }
        cli.System.Threading.Thread nativeThread = this.nativeThread;
        if (nativeThread == null) {
            return State.TERMINATED;
        }
        if ((nativeThread.get_ThreadState().Value & cli.System.Threading.ThreadState.WaitSleepJoin) != 0) {
            return State.BLOCKED;
        }
        return State.RUNNABLE;
    }

    // Added in JSR-166

    /**
     * Interface for handlers invoked when a <tt>Thread</tt> abruptly
     * terminates due to an uncaught exception.
     * <p>When a thread is about to terminate due to an uncaught exception
     * the Java Virtual Machine will query the thread for its
     * <tt>UncaughtExceptionHandler</tt> using
     * {@link #getUncaughtExceptionHandler} and will invoke the handler's
     * <tt>uncaughtException</tt> method, passing the thread and the
     * exception as arguments.
     * If a thread has not had its <tt>UncaughtExceptionHandler</tt>
     * explicitly set, then its <tt>ThreadGroup</tt> object acts as its
     * <tt>UncaughtExceptionHandler</tt>. If the <tt>ThreadGroup</tt> object
     * has no
     * special requirements for dealing with the exception, it can forward
     * the invocation to the {@linkplain #getDefaultUncaughtExceptionHandler
     * default uncaught exception handler}.
     *
     * @see #setDefaultUncaughtExceptionHandler
     * @see #setUncaughtExceptionHandler
     * @see ThreadGroup#uncaughtException
     * @since 1.5
     */
    public interface UncaughtExceptionHandler {
        /**
         * Method invoked when the given thread terminates due to the
         * given uncaught exception.
         * <p>Any exception thrown by this method will be ignored by the
         * Java Virtual Machine.
         * @param t the thread
         * @param e the exception
         */
        void uncaughtException(Thread t, Throwable e);
    }

    // null unless explicitly set
    private volatile UncaughtExceptionHandler uncaughtExceptionHandler;

    // null unless explicitly set
    private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;

    /**
     * Set the default handler invoked when a thread abruptly terminates
     * due to an uncaught exception, and no other handler has been defined
     * for that thread.
     *
     * <p>Uncaught exception handling is controlled first by the thread, then
     * by the thread's {@link ThreadGroup} object and finally by the default
     * uncaught exception handler. If the thread does not have an explicit
     * uncaught exception handler set, and the thread's thread group
     * (including parent thread groups)  does not specialize its
     * <tt>uncaughtException</tt> method, then the default handler's
     * <tt>uncaughtException</tt> method will be invoked.
     * <p>By setting the default uncaught exception handler, an application
     * can change the way in which uncaught exceptions are handled (such as
     * logging to a specific device, or file) for those threads that would
     * already accept whatever &quot;default&quot; behavior the system
     * provided.
     *
     * <p>Note that the default uncaught exception handler should not usually
     * defer to the thread's <tt>ThreadGroup</tt> object, as that could cause
     * infinite recursion.
     *
     * @param eh the object to use as the default uncaught exception handler.
     * If <tt>null</tt> then there is no default handler.
     *
     * @throws SecurityException if a security manager is present and it
     *         denies <tt>{@link RuntimePermission}
     *         (&quot;setDefaultUncaughtExceptionHandler&quot;)</tt>
     *
     * @see #setUncaughtExceptionHandler
     * @see #getUncaughtExceptionHandler
     * @see ThreadGroup#uncaughtException
     * @since 1.5
     */
    public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(
                new RuntimePermission("setDefaultUncaughtExceptionHandler")
                    );
        }

         defaultUncaughtExceptionHandler = eh;
     }

    /**
     * Returns the default handler invoked when a thread abruptly terminates
     * due to an uncaught exception. If the returned value is <tt>null</tt>,
     * there is no default.
     * @since 1.5
     * @see #setDefaultUncaughtExceptionHandler
     */
    public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler(){
        return defaultUncaughtExceptionHandler;
    }

    /**
     * Returns the handler invoked when this thread abruptly terminates
     * due to an uncaught exception. If this thread has not had an
     * uncaught exception handler explicitly set then this thread's
     * <tt>ThreadGroup</tt> object is returned, unless this thread
     * has terminated, in which case <tt>null</tt> is returned.
     * @since 1.5
     */
    public UncaughtExceptionHandler getUncaughtExceptionHandler() {
        return uncaughtExceptionHandler != null ?
            uncaughtExceptionHandler : group;
    }

    /**
     * Set the handler invoked when this thread abruptly terminates
     * due to an uncaught exception.
     * <p>A thread can take full control of how it responds to uncaught
     * exceptions by having its uncaught exception handler explicitly set.
     * If no such handler is set then the thread's <tt>ThreadGroup</tt>
     * object acts as its handler.
     * @param eh the object to use as this thread's uncaught exception
     * handler. If <tt>null</tt> then this thread has no explicit handler.
     * @throws  SecurityException  if the current thread is not allowed to
     *          modify this thread.
     * @see #setDefaultUncaughtExceptionHandler
     * @see ThreadGroup#uncaughtException
     * @since 1.5
     */
    public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
        checkAccess();
        uncaughtExceptionHandler = eh;
    }

    /**
     * Dispatch an uncaught exception to the handler. This method is
     * intended to be called only by the JVM.
     */
    private void dispatchUncaughtException(Throwable e) {
        getUncaughtExceptionHandler().uncaughtException(this, e);
    }

    /* Some private helper methods */
    private synchronized void setPriority0(int newPriority) {
        cli.System.Threading.Thread nativeThread = this.nativeThread;
        if (nativeThread != null) {
            try {
                if (false) throw new cli.System.Threading.ThreadStateException();
                nativeThread.set_Priority(cli.System.Threading.ThreadPriority.wrap(mapJavaPriorityToClr(newPriority)));
            }
            catch (cli.System.Threading.ThreadStateException _) {
            }
        }
    }

    private void stop0(Throwable x) {
        if (x == null) {
            throw new NullPointerException();
        }
        synchronized (lock) {
            if (!running) {
                stillborn = x;
                x = null;
            }
        }
        if (x != null) {
            // NOTE we allow ThreadDeath (and its subclasses) to be thrown on every thread, but any
            // other exception is ignored, except if we're throwing it on the current Thread. This
            // is done to allow exception handlers to be type specific, otherwise every exception
            // handler would have to catch ThreadAbortException and look inside it to see if it
            // contains the real exception that we wish to handle.
            // I hope we can get away with this behavior, because Thread.stop() is deprecated
            // anyway. Note that we do allow arbitrary exceptions to be thrown on the current
            // thread, since this is harmless (because they aren't wrapped) and also because it
            // provides some real value, because it is one of the ways you can throw arbitrary checked
            // exceptions from Java.
            if (this == current) {
                sun.misc.Unsafe.getUnsafe().throwException(x);
            }
            else if (x instanceof ThreadDeath) {
                cli.System.Threading.Thread nativeThread = this.nativeThread;
                if (nativeThread == null) {
                    return;
                }
                try {
                    if (false) throw new cli.System.Threading.ThreadStateException();
                    nativeThread.Abort(x);
                }
                catch (cli.System.Threading.ThreadStateException _) {
                    // .NET 2.0 throws a ThreadStateException if the target thread is currently suspended
                    // (but it does record the Abort request)
                }
                try {
                    if (false) throw new cli.System.Threading.ThreadStateException();
                    int suspend = cli.System.Threading.ThreadState.Suspended | cli.System.Threading.ThreadState.SuspendRequested;
                    while ((nativeThread.get_ThreadState().Value & suspend) != 0) {
                        nativeThread.Resume();
                    }
                }
                catch (cli.System.Threading.ThreadStateException _) {
                }
            }
        }
    }

    private void suspend0() {
        try {
            if (false) throw new cli.System.Threading.ThreadStateException();
            cli.System.Threading.Thread nativeThread = this.nativeThread;
            if (nativeThread != null) {
                nativeThread.Suspend();
            }
        }
        catch (cli.System.Threading.ThreadStateException _) {
        }
    }

    private void resume0() {
        try {
            if (false) throw new cli.System.Threading.ThreadStateException();
            cli.System.Threading.Thread nativeThread = this.nativeThread;
            if (nativeThread != null) {
                nativeThread.Resume();
            }
        }
        catch (cli.System.Threading.ThreadStateException _) {
        }
    }

    private void interrupt0() {
        synchronized (lock) {
            // if the thread hasn't been started yet or has been terminated, the interrupt is ignored
            // (like on the reference implementation)
            if (nativeThread == null) {
                return;
            }
            if (!interruptPending) {
                interruptPending = true;
                if (interruptableWait) {
                    nativeInterruptPending = true;
                    nativeThread.Interrupt();
                }
            }
        }
    }
   
    private void setRunningAndCheckStillborn() throws Throwable {
        Throwable x;
        synchronized (lock) {
            running = true;
            x = stillborn;
            stillborn = null;
        }
        if (x != null) {
            throw x;
        }
    }

    // [IKVM] this the entry point of thread started from Java
    @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation
    void threadProc() {
        current = this;
        try {
            // the body of the try block is in another method to allow the (limited) try/finally optimizer
            // to properly recognize the try/finally block, because we want to make sure that die()
            // runs in a finally block to prevent it from being asynchronously aborted.
            threadProc2();
        }
        finally {
            die();
        }
    }
   
    @cli.IKVM.Attributes.HideFromJavaAttribute.Annotation
    private void threadProc2() {
        try {
            setRunningAndCheckStillborn();
            run();
        }
        catch (Throwable x) {
            try {
                getUncaughtExceptionHandler().uncaughtException(this, x);
            }
            catch (Throwable _) {
            }
        }
    }

    // [IKVM] this the implementation of Object.wait(long timeout, int nanos). It is hooked up in map.xml.
    static void objectWait(Object o, long timeout, int nanos) throws InterruptedException {
        if (o == null) {
            throw new NullPointerException();
        }
        if (timeout < 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 && timeout == 0)) {
            timeout++;
        }
        objectWait(o, timeout);
    }

    // [IKVM] this the implementation of Object.wait(long timeout). It is hooked up in map.xml.
    static void objectWait(Object o, long timeout) throws InterruptedException {
        if (o == null) {
            throw new NullPointerException();
        }
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }
        Thread t = currentThread();
        t.enterInterruptableWait(timeout != 0);
        try {
            if (false) throw new cli.System.Threading.ThreadInterruptedException();
            if (timeout == 0 || timeout > 922337203685476L) {
                cli.System.Threading.Monitor.Wait(o);
            }
            else {
                // We wait a maximum of Integer.MAX_VALUE milliseconds, because that is the maximum that Monitor.Wait will wait.
                // Note that the Object.wait() specification allows for spurious wakeups, so this isn't a problem. Trying to
                // emulate a longer wait with multiple Monitor.Wait() calls is not allowed, because that would mean that
                // we acquire and release the synchronization lock multiple times during the wait.
                cli.System.Threading.Monitor.Wait(o, (int)Math.min(timeout, Integer.MAX_VALUE));
            }
        }
        catch (cli.System.Threading.ThreadInterruptedException _) {
        }
        finally {
            t.leaveInterruptableWait();
        }
    }
}
TOP

Related Classes of java.lang.Thread$UncaughtExceptionHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.