final class VMThread
{
    // Note: when this thread dies, this reference is *not* cleared
    private Thread thread;

    private VMThread(Thread thread, long stacksize)
    {
	this.thread = thread;
	start(stacksize);
    }

    private void run()
    {
	try
	{
	    try
	    {
		thread.run();
	    }
	    catch(Throwable t)
	    {
		ThreadGroup group = thread.group;
		if(group != null)
		{
		    group.uncaughtException(thread, t);
		}
	    }
	}
	finally
	{
	    ThreadGroup group = thread.group;
	    if(group != null)
	    {
		group.removeThread(thread);
		synchronized(thread)
		{
		    thread.group = null;
		    thread.vmThread = null;
		}
	    }
	}
    }

    static VMThread create(Thread thread, long stacksize)
    {
	return new VMThread(thread, stacksize);
    }

    static Thread currentThread()
    {
	VMThread vmThread = currentVMThread();
	if(vmThread.thread == null)
	{
	    vmThread.thread = new Thread(vmThread, null, Thread.NORM_PRIORITY, false);
	}
	return vmThread;
    }

    String getName()
    {
	return thread.name;
    }

    void setName(String name)
    {
    }

    int getPriority()
    {
        return thread.priority;
    }

    boolean isDaemon()
    {
        return thread.daemon;
    }

    void setDaemon(boolean daemon)
    {
    }

    int countStackFrames()
    {
	return 0;
    }

    void join(long ms, int ns) throws InterruptedException
    {
	if (ms == 0 && ns == 0)
	    while (thread.isAlive())
		sleep(1);
	else
	{
	    while (--ms >= 0)
	    {
		if (! thread.isAlive())
		    return;
		sleep(1);
	    }
	    sleep(0, ns);
	}
    }

    static native void start(long stacksize);
    static native VMThread currentVMThread();
    static native void yield();
    static native void sleep(long ms, int ns) throws InterruptedException;
    native void interrupt();
    static native boolean interrupted();
    native boolean isInterrupted();
    native void suspend();
    native void resume();
    native void setPriority(int priority);
    native void stop(Throwable t);
    static native boolean holdsLock(Object obj);
}
