/*
 * Copyright (c) 1994, 2025, 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.lang.ref.Reference;
import java.lang.reflect.Field;
import java.time.Duration;
import java.util.Map;
import java.util.HashMap;
import java.util.Objects;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.StructureViolationException;
import java.util.concurrent.locks.LockSupport;
import jdk.internal.event.ThreadSleepEvent;
import jdk.internal.misc.TerminatingThreadLocal;
import jdk.internal.misc.Unsafe;
import jdk.internal.misc.VM;
import jdk.internal.vm.Continuation;
import jdk.internal.vm.ScopedValueContainer;
import jdk.internal.vm.StackableScope;
import jdk.internal.vm.ThreadContainer;
import jdk.internal.vm.annotation.ForceInline;
import jdk.internal.vm.annotation.Hidden;
import jdk.internal.vm.annotation.IntrinsicCandidate;
import jdk.internal.vm.annotation.Stable;
import sun.nio.ch.Interruptible;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.NANOSECONDS;

/**
 * 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> {@code Thread} defines constructors and a {@link Builder} to create threads.
 * {@linkplain #start() Starting} a thread schedules it to execute its {@link #run() run}
 * method. The newly started thread executes concurrently with the thread that caused
 * it to start.
 *
 * <p> A thread <i>terminates</i> if either its {@code run} method completes normally,
 * or if its {@code run} method completes abruptly and the appropriate {@linkplain
 * Thread.UncaughtExceptionHandler uncaught exception handler} completes normally or
 * abruptly. With no code left to run, the thread has completed execution. The
 * {@link #join() join} method can be used to wait for a thread to terminate.
 *
 * <p> Threads have a unique {@linkplain #threadId() identifier} and a {@linkplain
 * #getName() name}. The identifier is generated when a {@code Thread} is created
 * and cannot be changed. The thread name can be specified when creating a thread
 * or can be {@linkplain #setName(String) changed} at a later time.
 *
 * <p> Threads support {@link ThreadLocal} variables. These are variables that are
 * local to a thread, meaning a thread can have a copy of a variable that is set to
 * a value that is independent of the value set by other threads. {@code Thread} also
 * supports {@link InheritableThreadLocal} variables that are thread local variables
 * that are inherited at thread creation time from the parent {@code Thread}.
 * {@code Thread} supports a special inheritable thread local for the thread
 * {@linkplain #getContextClassLoader() context-class-loader}.
 *
 * <h2><a id="platform-threads">Platform threads</a></h2>
 * <p> {@code Thread} supports the creation of <i>platform threads</i> that are
 * typically mapped 1:1 to kernel threads scheduled by the operating system.
 * Platform threads will usually have a large stack and other resources that are
 * maintained by the operating system. Platforms threads are suitable for executing
 * all types of tasks but may be a limited resource.
 *
 * <p> Platform threads get an automatically generated thread name by default.
 *
 * <p> Platform threads are designated <i>daemon</i> or <i>non-daemon</i> threads.
 * When the Java virtual machine starts up, there is usually one non-daemon
 * thread (the thread that typically calls the application's {@code main} method).
 * The <a href="Runtime.html#shutdown">shutdown sequence</a> begins when all started
 * non-daemon threads have terminated. Unstarted non-daemon threads do not prevent
 * the shutdown sequence from beginning.
 *
 * <p> In addition to the daemon status, platform threads have a {@linkplain
 * #getPriority() thread priority} and are members of a {@linkplain ThreadGroup
 * thread group}.
 *
 * <h2><a id="virtual-threads">Virtual threads</a></h2>
 * <p> {@code Thread} also supports the creation of <i>virtual threads</i>.
 * Virtual threads are typically <i>user-mode threads</i> scheduled by the Java
 * runtime rather than the operating system. Virtual threads will typically require
 * few resources and a single Java virtual machine may support millions of virtual
 * threads. Virtual threads are suitable for executing tasks that spend most of
 * the time blocked, often waiting for I/O operations to complete. Virtual threads
 * are not intended for long running CPU intensive operations.
 *
 * <p> Virtual threads typically employ a small set of platform threads used as
 * <em>carrier threads</em>. Locking and I/O operations are examples of operations
 * where a carrier thread may be re-scheduled from one virtual thread to another.
 * Code executing in a virtual thread is not aware of the underlying carrier thread.
 * The {@linkplain Thread#currentThread()} method, used to obtain a reference
 * to the <i>current thread</i>, will always return the {@code Thread} object
 * for the virtual thread.
 *
 * <p> Virtual threads do not have a thread name by default. The {@link #getName()
 * getName} method returns the empty string if a thread name is not set.
 *
 * <p> Virtual threads are daemon threads and so do not prevent the
 * <a href="Runtime.html#shutdown">shutdown sequence</a> from beginning.
 * Virtual threads have a fixed {@linkplain #getPriority() thread priority}
 * that cannot be changed.
 *
 * <h2>Creating and starting threads</h2>
 *
 * <p> {@code Thread} defines public constructors for creating platform threads and
 * the {@link #start() start} method to schedule threads to execute. {@code Thread}
 * may be extended for customization and other advanced reasons although most
 * applications should have little need to do this.
 *
 * <p> {@code Thread} defines a {@link Builder} API for creating and starting both
 * platform and virtual threads. The following are examples that use the builder:
 * {@snippet :
 *   Runnable runnable = ...
 *
 *   // Start a daemon thread to run a task
 *   Thread thread = Thread.ofPlatform().daemon().start(runnable);
 *
 *   // Create an unstarted thread with name "duke", its start() method
 *   // must be invoked to schedule it to execute.
 *   Thread thread = Thread.ofPlatform().name("duke").unstarted(runnable);
 *
 *   // A ThreadFactory that creates daemon threads named "worker-0", "worker-1", ...
 *   ThreadFactory factory = Thread.ofPlatform().daemon().name("worker-", 0).factory();
 *
 *   // Start a virtual thread to run a task
 *   Thread thread = Thread.ofVirtual().start(runnable);
 *
 *   // A ThreadFactory that creates virtual threads
 *   ThreadFactory factory = Thread.ofVirtual().factory();
 * }
 *
 * <h2><a id="inheritance">Inheritance when creating threads</a></h2>
 * A {@code Thread} created with one of the public constructors inherits the daemon
 * status and thread priority from the parent thread at the time that the child {@code
 * Thread} is created. The {@linkplain ThreadGroup thread group} is also inherited when
 * not provided to the constructor. When using a {@code Thread.Builder} to create a
 * platform thread, the daemon status, thread priority, and thread group are inherited
 * when not set on the builder. As with the constructors, inheriting from the parent
 * thread is done when the child {@code Thread} is created.
 *
 * <p> A {@code Thread} inherits its initial values of {@linkplain InheritableThreadLocal
 * inheritable-thread-local} variables (including the context class loader) from
 * the parent thread values at the time that the child {@code Thread} is created.
 * The 5-param {@linkplain Thread#Thread(ThreadGroup, Runnable, String, long, boolean)
 * constructor} can be used to create a thread that does not inherit its initial
 * values from the constructing thread. When using a {@code Thread.Builder}, the
 * {@link Builder#inheritInheritableThreadLocals(boolean) inheritInheritableThreadLocals}
 * method can be used to select if the initial values are inherited.
 *
 * <p> Unless otherwise specified, passing a {@code null} argument to a constructor
 * or method in this class will cause a {@link NullPointerException} to be thrown.
 *
 * @implNote
 * In the JDK Reference Implementation, the virtual thread scheduler may be configured
 * with the following system properties:
 * <table class="striped">
 * <caption style="display:none">System properties</caption>
 *   <thead>
 *   <tr>
 *     <th scope="col">System property</th>
 *     <th scope="col">Description</th>
 *   </tr>
 *   </thead>
 *   <tbody>
 *   <tr>
 *     <th scope="row">
 *       {@systemProperty jdk.virtualThreadScheduler.parallelism}
 *     </th>
 *     <td> The number of platform threads available for scheduling virtual
 *       threads. It defaults to the number of available processors. </td>
 *   </tr>
 *   <tr>
 *     <th scope="row">
 *       {@systemProperty jdk.virtualThreadScheduler.maxPoolSize}
 *     </th>
 *     <td> The maximum number of platform threads available to the scheduler.
 *       It defaults to 256. </td>
 *   </tr>
 *   </tbody>
 * </table>
 *
 * @since   1.0
 */
public class Thread implements Runnable {
    /* Make sure registerNatives is the first thing <clinit> does. */
    private static native void registerNatives();
    static {
        registerNatives();
    }

    /*
     * Reserved for exclusive use by the JVM. Cannot be moved to the FieldHolder
     * as it needs to be set by the VM for JNI attaching threads, before executing
     * the constructor that will create the FieldHolder. The historically named
     * `eetop` holds the address of the underlying VM JavaThread, and is set to
     * non-zero when the thread is started, and reset to zero when the thread terminates.
     * A non-zero value indicates this thread isAlive().
     */
    private volatile long eetop;

    // thread id
    private final long tid;

    // thread name
    private volatile String name;

    // interrupt status (read/written by VM)
    volatile boolean interrupted;

    // context ClassLoader
    private volatile ClassLoader contextClassLoader;

    // Additional fields for platform threads.
    // All fields, except task and terminatingThreadLocals, are accessed directly by the VM.
    private static class FieldHolder {
        final ThreadGroup group;
        final Runnable task;
        final long stackSize;
        volatile int priority;
        volatile boolean daemon;
        volatile int threadStatus;

        // This map is maintained by the ThreadLocal class
        ThreadLocal.ThreadLocalMap terminatingThreadLocals;

        FieldHolder(ThreadGroup group,
                    Runnable task,
                    long stackSize,
                    int priority,
                    boolean daemon) {
            this.group = group;
            this.task = task;
            this.stackSize = stackSize;
            this.priority = priority;
            if (daemon)
                this.daemon = true;
        }
    }
    private final FieldHolder holder;

    ThreadLocal.ThreadLocalMap terminatingThreadLocals() {
        return holder.terminatingThreadLocals;
    }

    void setTerminatingThreadLocals(ThreadLocal.ThreadLocalMap map) {
        holder.terminatingThreadLocals = map;
    }

    /*
     * ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class.
     */
    private ThreadLocal.ThreadLocalMap threadLocals;

    ThreadLocal.ThreadLocalMap threadLocals() {
        return threadLocals;
    }

    void setThreadLocals(ThreadLocal.ThreadLocalMap map) {
        threadLocals = map;
    }

    /*
     * InheritableThreadLocal values pertaining to this thread. This map is
     * maintained by the InheritableThreadLocal class.
     */
    private ThreadLocal.ThreadLocalMap inheritableThreadLocals;

    ThreadLocal.ThreadLocalMap inheritableThreadLocals() {
        return inheritableThreadLocals;
    }

    void setInheritableThreadLocals(ThreadLocal.ThreadLocalMap map) {
        inheritableThreadLocals = map;
    }

    /*
     * Scoped value bindings are maintained by the ScopedValue class.
     */
    private Object scopedValueBindings;

    // Special value to indicate this is a newly-created Thread
    // Note that his must match the declaration in ScopedValue.
    private static final Object NEW_THREAD_BINDINGS = Thread.class;

    static Object scopedValueBindings() {
        return currentThread().scopedValueBindings;
    }

    static void setScopedValueBindings(Object bindings) {
        currentThread().scopedValueBindings = bindings;
    }

    /**
     * Search the stack for the most recent scoped-value bindings.
     */
    @IntrinsicCandidate
    static native Object findScopedValueBindings();

    /**
     * Inherit the scoped-value bindings from the given container.
     * Invoked when starting a thread.
     */
    void inheritScopedValueBindings(ThreadContainer container) {
        ScopedValueContainer.BindingsSnapshot snapshot;
        if (container.owner() != null
                && (snapshot = container.scopedValueBindings()) != null) {

            // bindings established for running/calling an operation
            Object bindings = snapshot.scopedValueBindings();
            if (currentThread().scopedValueBindings != bindings) {
                throw new StructureViolationException("Scoped value bindings have changed");
            }

            this.scopedValueBindings = bindings;
        }
    }

    /*
     * Lock object for thread interrupt.
     */
    final Object interruptLock = new Object();

    /**
     * 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
     */
    private 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 Interruptible nioBlocker;

    Interruptible nioBlocker() {
        //assert Thread.holdsLock(interruptLock);
        return nioBlocker;
    }

    /* Set the blocker field; invoked via jdk.internal.access.SharedSecrets
     * from java.nio code
     */
    void blockedOn(Interruptible b) {
        //assert Thread.currentThread() == this;
        synchronized (interruptLock) {
            nioBlocker = b;
        }
    }

    /**
     * The minimum priority that a thread can have.
     */
    public static final int MIN_PRIORITY = 1;

    /**
     * The default priority that is assigned to a thread.
     */
    public static final int NORM_PRIORITY = 5;

    /**
     * The maximum priority that a thread can have.
     */
    public static final int MAX_PRIORITY = 10;

    /*
     * Current inner-most continuation.
     */
    private Continuation cont;

    /**
     * Returns the current continuation.
     */
    Continuation getContinuation() {
        return cont;
    }

    /**
     * Sets the current continuation.
     */
    void setContinuation(Continuation cont) {
        this.cont = cont;
    }

    /**
     * Returns the Thread object for the current platform thread. If the
     * current thread is a virtual thread then this method returns the carrier.
     */
    @IntrinsicCandidate
    static native Thread currentCarrierThread();

    /**
     * Returns the Thread object for the current thread.
     * @return  the current thread
     */
    @IntrinsicCandidate
    public static native Thread currentThread();

    /**
     * Sets the Thread object to be returned by Thread.currentThread().
     */
    @IntrinsicCandidate
    native void setCurrentThread(Thread thread);

    // ScopedValue support:

    @IntrinsicCandidate
    static native Object[] scopedValueCache();

    @IntrinsicCandidate
    static native void setScopedValueCache(Object[] cache);

    @IntrinsicCandidate
    static native void ensureMaterializedForStackWalk(Object o);

    /**
     * A hint to the scheduler that the current thread is willing to yield
     * its current use of a processor. The scheduler is free to ignore this
     * hint.
     *
     * <p> Yield is a heuristic attempt to improve relative progression
     * between threads that would otherwise over-utilise a CPU. Its use
     * should be combined with detailed profiling and benchmarking to
     * ensure that it actually has the desired effect.
     *
     * <p> It is rarely appropriate to use this method. It may be useful
     * for debugging or testing purposes, where it may help to reproduce
     * bugs due to race conditions. It may also be useful when designing
     * concurrency control constructs such as the ones in the
     * {@link java.util.concurrent.locks} package.
     */
    public static void yield() {
        if (currentThread() instanceof VirtualThread vthread) {
            vthread.tryYield();
        } else {
            yield0();
        }
    }

    private static native void yield0();

    /**
     * Called before sleeping to create a jdk.ThreadSleep event.
     */
    private static ThreadSleepEvent beforeSleep(long nanos) {
        try {
            ThreadSleepEvent event = new ThreadSleepEvent();
            if (event.isEnabled()) {
                event.time = nanos;
                event.begin();
                return event;
            }
        } catch (OutOfMemoryError e) {
            // ignore
        }
        return null;
    }


    /**
     * Called after sleeping to commit the jdk.ThreadSleep event.
     */
    private static void afterSleep(ThreadSleepEvent event) {
        if (event != null) {
            try {
                event.commit();
            } catch (OutOfMemoryError e) {
                // ignore
            }
        }
    }

    /**
     * Sleep for the specified number of nanoseconds, subject to the precision
     * and accuracy of system timers and schedulers.
     */
    private static void sleepNanos(long nanos) throws InterruptedException {
        ThreadSleepEvent event = beforeSleep(nanos);
        try {
            if (currentThread() instanceof VirtualThread vthread) {
                vthread.sleepNanos(nanos);
            } else {
                sleepNanos0(nanos);
            }
        } finally {
            afterSleep(event);
        }
    }

    private static native void sleepNanos0(long nanos) throws InterruptedException;

    /**
     * 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
     *
     * @throws  IllegalArgumentException
     *          if the value of {@code millis} is negative
     *
     * @throws  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 static void sleep(long millis) throws InterruptedException {
        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }
        long nanos = MILLISECONDS.toNanos(millis);
        sleepNanos(nanos);
    }

    /**
     * Causes the currently executing thread to sleep (temporarily 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
     *         {@code 0-999999} additional nanoseconds to sleep
     *
     * @throws  IllegalArgumentException
     *          if the value of {@code millis} is negative, or the value of
     *          {@code nanos} is not in the range {@code 0-999999}
     *
     * @throws  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 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");
        }

        // total sleep time, in nanoseconds
        long totalNanos = MILLISECONDS.toNanos(millis);
        totalNanos += Math.min(Long.MAX_VALUE - totalNanos, nanos);
        sleepNanos(totalNanos);
    }

    /**
     * Causes the currently executing thread to sleep (temporarily cease
     * execution) for the specified duration, subject to the precision and
     * accuracy of system timers and schedulers. This method is a no-op if
     * the duration is {@linkplain Duration#isNegative() negative}.
     *
     * @param  duration
     *         the duration to sleep
     *
     * @throws  InterruptedException
     *          if the current thread is interrupted while sleeping. The
     *          <i>interrupted status</i> of the current thread is
     *          cleared when this exception is thrown.
     *
     * @since 19
     */
    public static void sleep(Duration duration) throws InterruptedException {
        long nanos = NANOSECONDS.convert(duration);  // MAX_VALUE if > 292 years
        if (nanos < 0) {
            return;
        }
        sleepNanos(nanos);
    }

    /**
     * Indicates that the caller is momentarily unable to progress, until the
     * occurrence of one or more actions on the part of other activities. By
     * invoking this method within each iteration of a spin-wait loop construct,
     * the calling thread indicates to the runtime that it is busy-waiting.
     * The runtime may take action to improve the performance of invoking
     * spin-wait loop constructions.
     *
     * @apiNote
     * As an example consider a method in a class that spins in a loop until
     * some flag is set outside of that method. A call to the {@code onSpinWait}
     * method should be placed inside the spin loop.
     * {@snippet :
     *     class EventHandler {
     *         volatile boolean eventNotificationNotReceived;
     *         void waitForEventAndHandleIt() {
     *             while ( eventNotificationNotReceived ) {
     *                 Thread.onSpinWait();
     *             }
     *             readAndProcessEvent();
     *         }
     *
     *         void readAndProcessEvent() {
     *             // Read event from some source and process it
     *              . . .
     *         }
     *     }
     * }
     * <p>
     * The code above would remain correct even if the {@code onSpinWait}
     * method was not called at all. However on some architectures the Java
     * Virtual Machine may issue the processor instructions to address such
     * code patterns in a more beneficial way.
     *
     * @since 9
     */
    @IntrinsicCandidate
    public static void onSpinWait() {}

    /**
     * Characteristic value signifying that initial values for {@link
     * InheritableThreadLocal inheritable-thread-locals} are not inherited from
     * the constructing thread.
     * See Thread initialization.
     */
    static final int NO_INHERIT_THREAD_LOCALS = 1 << 2;

    /**
     * Thread identifier assigned to the primordial thread.
     */
    static final long PRIMORDIAL_TID = 3;

    /**
     * Helper class to generate thread identifiers. The identifiers start at
     * {@link Thread#PRIMORDIAL_TID}&nbsp;+1 as this class cannot be used during
     * early startup to generate the identifier for the primordial thread. The
     * counter is off-heap and shared with the VM to allow it to assign thread
     * identifiers to non-Java threads.
     * See Thread initialization.
     */
    private static class ThreadIdentifiers {
        private static final Unsafe U;
        private static final long NEXT_TID_OFFSET;
        static {
            U = Unsafe.getUnsafe();
            NEXT_TID_OFFSET = Thread.getNextThreadIdOffset();
        }
        static long next() {
            return U.getAndAddLong(null, NEXT_TID_OFFSET, 1);
        }
    }

    /**
     * Initializes a platform Thread.
     *
     * @param g the Thread group, can be null
     * @param name the name of the new Thread
     * @param characteristics thread characteristics
     * @param task the object whose run() method gets called
     * @param stackSize the desired stack size for the new thread, or
     *        zero to indicate that this parameter is to be ignored.
     */
    Thread(ThreadGroup g, String name, int characteristics, Runnable task, long stackSize) {

        Thread parent = currentThread();
        boolean attached = (parent == this);   // primordial or JNI attached

        if (attached) {
            if (g == null) {
                throw new InternalError("group cannot be null when attaching");
            }
            this.holder = new FieldHolder(g, task, stackSize, NORM_PRIORITY, false);
        } else {
            if (g == null) {
                // default to current thread's group
                g = parent.getThreadGroup();
            }
            int priority = Math.min(parent.getPriority(), g.getMaxPriority());
            this.holder = new FieldHolder(g, task, stackSize, priority, parent.isDaemon());
        }

        if (attached && VM.initLevel() < 1) {
            this.tid = PRIMORDIAL_TID;  // primordial thread
        } else {
            this.tid = ThreadIdentifiers.next();
        }

        this.name = (name != null) ? name : genThreadName();

        // thread locals
        if (!attached) {
            if ((characteristics & NO_INHERIT_THREAD_LOCALS) == 0) {
                ThreadLocal.ThreadLocalMap parentMap = parent.inheritableThreadLocals;
                if (parentMap != null && parentMap.size() > 0) {
                    this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parentMap);
                }
                if (VM.isBooted()) {
                    this.contextClassLoader = parent.getContextClassLoader();
                }
            } else if (VM.isBooted()) {
                // default CCL to the system class loader when not inheriting
                this.contextClassLoader = ClassLoader.getSystemClassLoader();
            }
        }

        // special value to indicate this is a newly-created Thread
        // Note that his must match the declaration in ScopedValue.
        this.scopedValueBindings = NEW_THREAD_BINDINGS;
    }

    /**
     * Initializes a virtual Thread.
     *
     * @param name thread name, can be null
     * @param characteristics thread characteristics
     * @param bound true when bound to an OS thread
     */
    Thread(String name, int characteristics, boolean bound) {
        this.tid = ThreadIdentifiers.next();
        this.name = (name != null) ? name : "";

        // thread locals
        if ((characteristics & NO_INHERIT_THREAD_LOCALS) == 0) {
            Thread parent = currentThread();
            ThreadLocal.ThreadLocalMap parentMap = parent.inheritableThreadLocals;
            if (parentMap != null && parentMap.size() > 0) {
                this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parentMap);
            }
            this.contextClassLoader = parent.getContextClassLoader();
        } else {
            // default CCL to the system class loader when not inheriting
            this.contextClassLoader = ClassLoader.getSystemClassLoader();
        }

        // special value to indicate this is a newly-created Thread
        this.scopedValueBindings = NEW_THREAD_BINDINGS;

        // create a FieldHolder object, needed when bound to an OS thread
        if (bound) {
            ThreadGroup g = Constants.VTHREAD_GROUP;
            int pri = NORM_PRIORITY;
            this.holder = new FieldHolder(g, null, -1, pri, true);
        } else {
            this.holder = null;
        }
    }

    /**
     * Returns a builder for creating a platform {@code Thread} or {@code ThreadFactory}
     * that creates platform threads.
     *
     * @apiNote The following are examples using the builder:
     * {@snippet :
     *   // Start a daemon thread to run a task
     *   Thread thread = Thread.ofPlatform().daemon().start(runnable);
     *
     *   // Create an unstarted thread with name "duke", its start() method
     *   // must be invoked to schedule it to execute.
     *   Thread thread = Thread.ofPlatform().name("duke").unstarted(runnable);
     *
     *   // A ThreadFactory that creates daemon threads named "worker-0", "worker-1", ...
     *   ThreadFactory factory = Thread.ofPlatform().daemon().name("worker-", 0).factory();
     * }
     *
     * @return A builder for creating {@code Thread} or {@code ThreadFactory} objects.
     * @since 21
     */
    public static Builder.OfPlatform ofPlatform() {
        return new ThreadBuilders.PlatformThreadBuilder();
    }

    /**
     * Returns a builder for creating a virtual {@code Thread} or {@code ThreadFactory}
     * that creates virtual threads.
     *
     * @apiNote The following are examples using the builder:
     * {@snippet :
     *   // Start a virtual thread to run a task.
     *   Thread thread = Thread.ofVirtual().start(runnable);
     *
     *   // A ThreadFactory that creates virtual threads
     *   ThreadFactory factory = Thread.ofVirtual().factory();
     * }
     *
     * @return A builder for creating {@code Thread} or {@code ThreadFactory} objects.
     * @since 21
     */
    public static Builder.OfVirtual ofVirtual() {
        return new ThreadBuilders.VirtualThreadBuilder();
    }

    /**
     * A builder for {@link Thread} and {@link ThreadFactory} objects.
     *
     * <p> {@code Builder} defines methods to set {@code Thread} properties such
     * as the thread {@link #name(String) name}. This includes properties that would
     * otherwise be <a href="Thread.html#inheritance">inherited</a>. Once set, a
     * {@code Thread} or {@code ThreadFactory} is created with the following methods:
     *
     * <ul>
     *     <li> The {@linkplain #unstarted(Runnable) unstarted} method creates a new
     *          <em>unstarted</em> {@code Thread} to run a task. The {@code Thread}'s
     *          {@link Thread#start() start} method must be invoked to schedule the
     *          thread to execute.
     *     <li> The {@linkplain #start(Runnable) start} method creates a new {@code
     *          Thread} to run a task and schedules the thread to execute.
     *     <li> The {@linkplain #factory() factory} method creates a {@code ThreadFactory}.
     * </ul>
     *
     * <p> A {@code Thread.Builder} is not thread safe. The {@code ThreadFactory}
     * returned by the builder's {@code factory()} method is thread safe.
     *
     * <p> Unless otherwise specified, passing a null argument to a method in
     * this interface causes a {@code NullPointerException} to be thrown.
     *
     * @see Thread#ofPlatform()
     * @see Thread#ofVirtual()
     * @since 21
     */
    public sealed interface Builder
            permits Builder.OfPlatform, Builder.OfVirtual {

        /**
         * Sets the thread name.
         * @param name thread name
         * @return this builder
         */
        Builder name(String name);

        /**
         * Sets the thread name to be the concatenation of a string prefix and
         * the string representation of a counter value. The counter's initial
         * value is {@code start}. It is incremented after a {@code Thread} is
         * created with this builder so that the next thread is named with
         * the new counter value. A {@code ThreadFactory} created with this
         * builder is seeded with the current value of the counter. The {@code
         * ThreadFactory} increments its copy of the counter after {@link
         * ThreadFactory#newThread(Runnable) newThread} is used to create a
         * {@code Thread}.
         *
         * @apiNote
         * The following example creates a builder that is invoked twice to start
         * two threads named "{@code worker-0}" and "{@code worker-1}".
         * {@snippet :
         *   Thread.Builder builder = Thread.ofPlatform().name("worker-", 0);
         *   Thread t1 = builder.start(task1);   // name "worker-0"
         *   Thread t2 = builder.start(task2);   // name "worker-1"
         * }
         *
         * @param prefix thread name prefix
         * @param start the starting value of the counter
         * @return this builder
         * @throws IllegalArgumentException if start is negative
         */
        Builder name(String prefix, long start);

        /**
         * Sets whether the thread inherits the initial values of {@linkplain
         * InheritableThreadLocal inheritable-thread-local} variables from the
         * constructing thread. The default is to inherit.
         *
         * @param inherit {@code true} to inherit, {@code false} to not inherit
         * @return this builder
         */
        Builder inheritInheritableThreadLocals(boolean inherit);

        /**
         * Sets the uncaught exception handler.
         * @param ueh uncaught exception handler
         * @return this builder
         */
        Builder uncaughtExceptionHandler(UncaughtExceptionHandler ueh);

        /**
         * Creates a new {@code Thread} from the current state of the builder to
         * run the given task. The {@code Thread}'s {@link Thread#start() start}
         * method must be invoked to schedule the thread to execute.
         *
         * @param task the object to run when the thread executes
         * @return a new unstarted Thread
         *
         * @see <a href="Thread.html#inheritance">Inheritance when creating threads</a>
         */
        Thread unstarted(Runnable task);

        /**
         * Creates a new {@code Thread} from the current state of the builder and
         * schedules it to execute.
         *
         * @param task the object to run when the thread executes
         * @return a new started Thread
         *
         * @see <a href="Thread.html#inheritance">Inheritance when creating threads</a>
         */
        Thread start(Runnable task);

        /**
         * Returns a {@code ThreadFactory} to create threads from the current
         * state of the builder. The returned thread factory is safe for use by
         * multiple concurrent threads.
         *
         * @return a thread factory to create threads
         */
        ThreadFactory factory();

        /**
         * A builder for creating a platform {@link Thread} or {@link ThreadFactory}
         * that creates platform threads.
         *
         * <p> Unless otherwise specified, passing a null argument to a method in
         * this interface causes a {@code NullPointerException} to be thrown.
         *
         * @see Thread#ofPlatform()
         * @since 21
         */
        sealed interface OfPlatform extends Builder
                permits ThreadBuilders.PlatformThreadBuilder {

            @Override OfPlatform name(String name);

            /**
             * @throws IllegalArgumentException {@inheritDoc}
             */
            @Override OfPlatform name(String prefix, long start);

            @Override OfPlatform inheritInheritableThreadLocals(boolean inherit);
            @Override OfPlatform uncaughtExceptionHandler(UncaughtExceptionHandler ueh);

            /**
             * Sets the thread group.
             * @param group the thread group
             * @return this builder
             */
            OfPlatform group(ThreadGroup group);

            /**
             * Sets the daemon status.
             * @param on {@code true} to create daemon threads
             * @return this builder
             */
            OfPlatform daemon(boolean on);

            /**
             * Sets the daemon status to {@code true}.
             * @implSpec The default implementation invokes {@linkplain #daemon(boolean)} with
             * a value of {@code true}.
             * @return this builder
             */
            default OfPlatform daemon() {
                return daemon(true);
            }

            /**
             * Sets the thread priority.
             * @param priority priority
             * @return this builder
             * @throws IllegalArgumentException if the priority is less than
             *        {@link Thread#MIN_PRIORITY} or greater than {@link Thread#MAX_PRIORITY}
             */
            OfPlatform priority(int priority);

            /**
             * Sets the desired stack size.
             *
             * <p> The stack size is the approximate number of bytes of address space
             * that the Java virtual machine is to allocate for the thread's stack. The
             * effect is highly platform dependent and the Java virtual machine is free
             * to treat the {@code stackSize} parameter as a "suggestion". If the value
             * is unreasonably low for the platform then a platform specific minimum
             * may be used. If the value is unreasonably high then a platform specific
             * maximum may be used. A value of zero is always ignored.
             *
             * @param stackSize the desired stack size
             * @return this builder
             * @throws IllegalArgumentException if the stack size is negative
             */
            OfPlatform stackSize(long stackSize);
        }

        /**
         * A builder for creating a virtual {@link Thread} or {@link ThreadFactory}
         * that creates virtual threads.
         *
         * <p> Unless otherwise specified, passing a null argument to a method in
         * this interface causes a {@code NullPointerException} to be thrown.
         *
         * @see Thread#ofVirtual()
         * @since 21
         */
        sealed interface OfVirtual extends Builder
                permits ThreadBuilders.VirtualThreadBuilder {

            @Override OfVirtual name(String name);

            /**
             * @throws IllegalArgumentException {@inheritDoc}
             */
            @Override OfVirtual name(String prefix, long start);

            @Override OfVirtual inheritInheritableThreadLocals(boolean inherit);
            @Override OfVirtual uncaughtExceptionHandler(UncaughtExceptionHandler ueh);
        }
    }

    /**
     * Throws CloneNotSupportedException as a Thread can not be meaningfully
     * cloned. Construct a new Thread instead.
     *
     * @throws  CloneNotSupportedException
     *          always
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException();
    }

    /**
     * Helper class for auto-numbering platform threads. The numbers start at
     * 0 and are separate from the thread identifier for historical reasons.
     */
    private static class ThreadNumbering {
        private static final Unsafe U;
        private static final Object NEXT_BASE;
        private static final long NEXT_OFFSET;
        static {
            U = Unsafe.getUnsafe();
            try {
                Field nextField = ThreadNumbering.class.getDeclaredField("next");
                NEXT_BASE = U.staticFieldBase(nextField);
                NEXT_OFFSET = U.staticFieldOffset(nextField);
            } catch (NoSuchFieldException e) {
                throw new ExceptionInInitializerError(e);
            }
        }
        private static volatile int next;
        static int next() {
            return U.getAndAddInt(NEXT_BASE, NEXT_OFFSET, 1);
        }
    }

    /**
     * Generates a thread name of the form {@code Thread-<n>}.
     */
    static String genThreadName() {
        return "Thread-" + ThreadNumbering.next();
    }

    /**
     * Throws NullPointerException if the name is null. Avoids use of
     * Objects.requireNonNull in early startup.
     */
    private static String checkName(String name) {
        if (name == null)
            throw new NullPointerException("'name' is null");
        return name;
    }

    /**
     * Initializes a new platform {@code Thread}. This constructor has the same
     * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
     * {@code (null, null, gname)}, where {@code gname} is a newly generated
     * name. Automatically generated names are of the form
     * {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer.
     *
     * <p> This constructor is only useful when extending {@code Thread} to
     * override the {@link #run()} method.
     *
     * @see <a href="#inheritance">Inheritance when creating threads</a>
     */
    public Thread() {
        this(null, null, 0, null, 0);
    }

    /**
     * Initializes a new platform {@code Thread}. This constructor has the same
     * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
     * {@code (null, task, gname)}, where {@code gname} is a newly generated
     * name. Automatically generated names are of the form
     * {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer.
     *
     * <p> For a non-null task, invoking this constructor directly is equivalent to:
     * <pre>{@code Thread.ofPlatform().unstarted(task); }</pre>
     *
     * @param  task
     *         the object whose {@code run} method is invoked when this thread
     *         is started. If {@code null}, this classes {@code run} method does
     *         nothing.
     *
     * @see <a href="#inheritance">Inheritance when creating threads</a>
     */
    public Thread(Runnable task) {
        this(null, null, 0, task, 0);
    }

    /**
     * Initializes a new platform {@code Thread}. This constructor has the same
     * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
     * {@code (group, task, gname)}, where {@code gname} is a newly generated
     * name. Automatically generated names are of the form
     * {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer.
     *
     * <p> For a non-null group and task, invoking this constructor directly is
     * equivalent to:
     * <pre>{@code Thread.ofPlatform().group(group).unstarted(task); }</pre>
     *
     * @param  group
     *         the thread group. If {@code null} the group
     *         is set to the current thread's thread group.
     *
     * @param  task
     *         the object whose {@code run} method is invoked when this thread
     *         is started. If {@code null}, this thread's run method is invoked.
     *
     * @see <a href="#inheritance">Inheritance when creating threads</a>
     */
    public Thread(ThreadGroup group, Runnable task) {
        this(group, null, 0, task, 0);
    }

    /**
     * Initializes a new platform {@code Thread}. This constructor has the same
     * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
     * {@code (null, null, name)}.
     *
     * <p> This constructor is only useful when extending {@code Thread} to
     * override the {@link #run()} method.
     *
     * @param   name
     *          the name of the new thread
     *
     * @see <a href="#inheritance">Inheritance when creating threads</a>
     */
    public Thread(String name) {
        this(null, checkName(name), 0, null, 0);
    }

    /**
     * Initializes a new platform {@code Thread}. This constructor has the same
     * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
     * {@code (group, null, name)}.
     *
     * <p> This constructor is only useful when extending {@code Thread} to
     * override the {@link #run()} method.
     *
     * @param  group
     *         the thread group. If {@code null}, the group
     *         is set to the current thread's thread group.
     *
     * @param  name
     *         the name of the new thread
     *
     * @see <a href="#inheritance">Inheritance when creating threads</a>
     */
    public Thread(ThreadGroup group, String name) {
        this(group, checkName(name), 0, null, 0);
    }

    /**
     * Initializes a new platform {@code Thread}. This constructor has the same
     * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
     * {@code (null, task, name)}.
     *
     * <p> For a non-null task and name, invoking this constructor directly is
     * equivalent to:
     * <pre>{@code Thread.ofPlatform().name(name).unstarted(task); }</pre>
     *
     * @param  task
     *         the object whose {@code run} method is invoked when this thread
     *         is started. If {@code null}, this thread's run method is invoked.
     *
     * @param  name
     *         the name of the new thread
     *
     * @see <a href="#inheritance">Inheritance when creating threads</a>
     */
    public Thread(Runnable task, String name) {
        this(null, checkName(name), 0, task, 0);
    }

    /**
     * Initializes a new platform {@code Thread} so that it has {@code task}
     * as its run object, has the specified {@code name} as its name,
     * and belongs to the thread group referred to by {@code group}.
     *
     * <p>The priority of the newly created thread is the smaller of
     * priority of the thread creating it and the maximum permitted
     * priority of the thread group. The method {@linkplain #setPriority
     * setPriority} 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 {@linkplain #setDaemon setDaemon}
     * may be used to change whether or not a thread is a daemon.
     *
     * <p>For a non-null group, task, and name, invoking this constructor directly
     * is equivalent to:
     * <pre>{@code Thread.ofPlatform().group(group).name(name).unstarted(task); }</pre>
     *
     * @param  group
     *         the thread group. If {@code null}, the group
     *         is set to the current thread's thread group.
     *
     * @param  task
     *         the object whose {@code run} method is invoked when this thread
     *         is started. If {@code null}, this thread's run method is invoked.
     *
     * @param  name
     *         the name of the new thread
     *
     * @see <a href="#inheritance">Inheritance when creating threads</a>
     */
    public Thread(ThreadGroup group, Runnable task, String name) {
        this(group, checkName(name), 0, task, 0);
    }

    /**
     * Initializes a new platform {@code Thread} so that it has {@code task}
     * as its run object, has the specified {@code name} as its name,
     * and belongs to the thread group referred to by {@code group}, 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
     * {@code stackSize} parameter, if any, is highly platform dependent.</b>
     *
     * <p>On some platforms, specifying a higher value for the
     * {@code stackSize} 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 {@code stackSize} parameter
     * and the maximum recursion depth and concurrency level are
     * platform-dependent.  <b>On some platforms, the value of the
     * {@code stackSize} parameter may have no effect whatsoever.</b>
     *
     * <p>The virtual machine is free to treat the {@code stackSize}
     * 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 {@code stackSize} parameter will
     * cause this constructor to behave exactly like the
     * {@code Thread(ThreadGroup, Runnable, String)} 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
     * {@code stackSize} parameter.
     *
     * <p>For a non-null group, task, and name, invoking this constructor directly
     * is equivalent to:
     * <pre>{@code Thread.ofPlatform().group(group).name(name).stackSize(stackSize).unstarted(task); }</pre>
     *
     * @param  group
     *         the thread group. If {@code null}, the group
     *         is set to the current thread's thread group.
     *
     * @param  task
     *         the object whose {@code run} method is invoked when this thread
     *         is started. If {@code null}, this thread's run method is invoked.
     *
     * @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.
     *
     * @since 1.4
     * @see <a href="#inheritance">Inheritance when creating threads</a>
     */
    public Thread(ThreadGroup group, Runnable task, String name, long stackSize) {
        this(group, checkName(name), 0, task, stackSize);
    }

    /**
     * Initializes a new platform {@code Thread} so that it has {@code task}
     * as its run object, has the specified {@code name} as its name,
     * belongs to the thread group referred to by {@code group}, has
     * the specified {@code stackSize}, and inherits initial values for
     * {@linkplain InheritableThreadLocal inheritable thread-local} variables
     * if {@code inheritThreadLocals} is {@code true}.
     *
     * <p> This constructor is identical to {@link
     * #Thread(ThreadGroup,Runnable,String,long)} with the added ability to
     * suppress, or not, the inheriting of initial values for inheritable
     * thread-local variables from the constructing thread. This allows for
     * finer grain control over inheritable thread-locals. Care must be taken
     * when passing a value of {@code false} for {@code inheritThreadLocals},
     * as it may lead to unexpected behavior if the new thread executes code
     * that expects a specific thread-local value to be inherited.
     *
     * <p> Specifying a value of {@code true} for the {@code inheritThreadLocals}
     * parameter will cause this constructor to behave exactly like the
     * {@code Thread(ThreadGroup, Runnable, String, long)} constructor.
     *
     * <p> For a non-null group, task, and name, invoking this constructor directly
     * is equivalent to:
     * <pre>{@code Thread.ofPlatform()
     *      .group(group)
     *      .name(name)
     *      .stackSize(stackSize)
     *      .inheritInheritableThreadLocals(inheritInheritableThreadLocals)
     *      .unstarted(task); }</pre>
     *
     * @param  group
     *         the thread group. If {@code null}, the group
     *         is set to the current thread's thread group.
     *
     * @param  task
     *         the object whose {@code run} method is invoked when this thread
     *         is started. If {@code null}, this thread's run method is invoked.
     *
     * @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
     *
     * @param  inheritInheritableThreadLocals
     *         if {@code true}, inherit initial values for inheritable
     *         thread-locals from the constructing thread, otherwise no initial
     *         values are inherited
     *
     * @since 9
     * @see <a href="#inheritance">Inheritance when creating threads</a>
     */
    public Thread(ThreadGroup group, Runnable task, String name,
                  long stackSize, boolean inheritInheritableThreadLocals) {
        this(group, checkName(name),
                (inheritInheritableThreadLocals ? 0 : NO_INHERIT_THREAD_LOCALS),
                task, stackSize);
    }

    /**
     * Creates a virtual thread to execute a task and schedules it to execute.
     *
     * <p> This method is equivalent to:
     * <pre>{@code Thread.ofVirtual().start(task); }</pre>
     *
     * @param task the object to run when the thread executes
     * @return a new, and started, virtual thread
     * @see <a href="#inheritance">Inheritance when creating threads</a>
     * @since 21
     */
    public static Thread startVirtualThread(Runnable task) {
        Objects.requireNonNull(task);
        var thread = ThreadBuilders.newVirtualThread(null, null, 0, task);
        thread.start();
        return thread;
    }

    /**
     * Returns {@code true} if this thread is a virtual thread. A virtual thread
     * is scheduled by the Java virtual machine rather than the operating system.
     *
     * @return {@code true} if this thread is a virtual thread
     *
     * @since 21
     */
    public final boolean isVirtual() {
        return (this instanceof BaseVirtualThread);
    }

    /**
     * Schedules this thread to begin execution. The thread will execute
     * independently of the current thread.
     *
     * <p> A thread can be started at most once. In particular, a thread can not
     * be restarted after it has terminated.
     *
     * @throws IllegalThreadStateException if the thread was already started
     */
    public void start() {
        synchronized (this) {
            // zero status corresponds to state "NEW".
            if (holder.threadStatus != 0)
                throw new IllegalThreadStateException();
            start0();
        }
    }

    /**
     * Schedules this thread to begin execution in the given thread container.
     * @throws IllegalStateException if the container is shutdown or closed
     * @throws IllegalThreadStateException if the thread has already been started
     */
    void start(ThreadContainer container) {
        synchronized (this) {
            // zero status corresponds to state "NEW".
            if (holder.threadStatus != 0)
                throw new IllegalThreadStateException();

            // bind thread to container
            if (this.container != null)
                throw new IllegalThreadStateException();
            setThreadContainer(container);

            // start thread
            boolean started = false;
            container.add(this);  // may throw
            try {
                // scoped values may be inherited
                inheritScopedValueBindings(container);

                start0();
                started = true;
            } finally {
                if (!started) {
                    container.remove(this);
                }
            }
        }
    }

    private native void start0();

    /**
     * This method is run by the thread when it executes. Subclasses of {@code
     * Thread} may override this method.
     *
     * <p> This method is not intended to be invoked directly. If this thread is a
     * platform thread created with a {@link Runnable} task then invoking this method
     * will invoke the task's {@code run} method. If this thread is a virtual thread
     * then invoking this method directly does nothing.
     *
     * @implSpec The default implementation executes the {@link Runnable} task that
     * the {@code Thread} was created with. If the thread was created without a task
     * then this method does nothing.
     */
    @Override
    public void run() {
        Runnable task = holder.task;
        if (task != null) {
            Object bindings = scopedValueBindings();
            runWith(bindings, task);
        }
    }

    /**
     * The VM recognizes this method as special, so any changes to the
     * name or signature require corresponding changes in
     * JVM_FindScopedValueBindings().
     */
    @Hidden
    @ForceInline
    final void runWith(Object bindings, Runnable op) {
        ensureMaterializedForStackWalk(bindings);
        op.run();
        Reference.reachabilityFence(bindings);
    }

    /**
     * Null out reference after Thread termination.
     */
    void clearReferences() {
        threadLocals = null;
        inheritableThreadLocals = null;
        if (uncaughtExceptionHandler != null)
            uncaughtExceptionHandler = null;
        if (nioBlocker != null)
            nioBlocker = null;
    }

    /**
     * This method is called by the VM to give a Thread
     * a chance to clean up before it actually exits.
     */
    private void exit() {
        try {
            // pop any remaining scopes from the stack, this may block
            if (headStackableScopes != null) {
                StackableScope.popAll();
            }
        } finally {
            // notify container that thread is exiting
            ThreadContainer container = threadContainer();
            if (container != null) {
                container.remove(this);
            }
        }

        try {
            if (terminatingThreadLocals() != null) {
                TerminatingThreadLocal.threadTerminated();
            }
        } finally {
            clearReferences();
        }
    }

    /**
     * Throws {@code UnsupportedOperationException}.
     *
     * @throws  UnsupportedOperationException always
     *
     * @deprecated This method was originally specified to "stop" a victim
     *       thread by causing the victim thread to throw a {@link ThreadDeath}.
     *       It was inherently unsafe. Stopping a thread caused it to unlock
     *       all of the monitors that it had locked (as a natural consequence
     *       of the {@code ThreadDeath} exception propagating up the stack). If
     *       any of the objects previously protected by these monitors were in
     *       an inconsistent state, the damaged objects became visible to
     *       other threads, potentially resulting in arbitrary behavior.
     *       Usages of {@code stop} 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} method should be used to
     *       interrupt the wait.
     *       For more information, see
     *       <a href="{@docRoot}/java.base/java/lang/doc-files/threadPrimitiveDeprecation.html">Why
     *       is Thread.stop deprecated and the ability to stop a thread removed?</a>.
     */
    @Deprecated(since="1.2", forRemoval=true)
    public final void stop() {
        throw new UnsupportedOperationException();
    }

    /**
     * Interrupts this thread.
     *
     * <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 InterruptibleChannel}
     * 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.
     *
     * @implNote In the JDK Reference Implementation, interruption of a thread
     * that is not alive still records that the interrupt request was made and
     * will report it via {@link #interrupted()} and {@link #isInterrupted()}.
     */
    public void interrupt() {
        // Setting the interrupt status must be done before reading nioBlocker.
        interrupted = true;
        interrupt0();  // inform VM of interrupt

        // thread may be blocked in an I/O operation
        if (this != Thread.currentThread()) {
            Interruptible blocker;
            synchronized (interruptLock) {
                blocker = nioBlocker;
                if (blocker != null) {
                    blocker.interrupt(this);
                }
            }
            if (blocker != null) {
                blocker.postInterrupt();
            }
        }
    }

    /**
     * Tests whether the current thread has been interrupted.  The
     * <i>interrupted status</i> of the thread is cleared by this method.  In
     * other words, if this method were to be called twice in succession, the
     * second call would return false (unless the current thread were
     * interrupted again, after the first call had cleared its interrupted
     * status and before the second call had examined it).
     *
     * @return  {@code true} if the current thread has been interrupted;
     *          {@code false} otherwise.
     * @see #isInterrupted()
     */
    public static boolean interrupted() {
        return currentThread().getAndClearInterrupt();
    }

    /**
     * Tests whether this thread has been interrupted.  The <i>interrupted
     * status</i> of the thread is unaffected by this method.
     *
     * @return  {@code true} if this thread has been interrupted;
     *          {@code false} otherwise.
     * @see     #interrupted()
     */
    public boolean isInterrupted() {
        return interrupted;
    }

    final void setInterrupt() {
        // assert Thread.currentCarrierThread() == this;
        if (!interrupted) {
            interrupted = true;
            interrupt0();  // inform VM of interrupt
        }
    }

    final void clearInterrupt() {
        // assert Thread.currentCarrierThread() == this;
        if (interrupted) {
            interrupted = false;
            clearInterruptEvent();
        }
    }

    boolean getAndClearInterrupt() {
        boolean oldValue = interrupted;
        // We may have been interrupted the moment after we read the field,
        // so only clear the field if we saw that it was set and will return
        // true; otherwise we could lose an interrupt.
        if (oldValue) {
            interrupted = false;
            clearInterruptEvent();
        }
        return oldValue;
    }

    /**
     * Tests if this thread is alive. A thread is alive if it has
     * been started and has not yet terminated.
     *
     * @return  {@code true} if this thread is alive;
     *          {@code false} otherwise.
     */
    public final boolean isAlive() {
        return alive();
    }

    /**
     * Returns true if this thread is alive.
     * This method is non-final so it can be overridden.
     */
    boolean alive() {
        return eetop != 0;
    }

    /**
     * Changes the priority of this thread.
     *
     * For platform threads, the priority is set to the smaller of the specified
     * {@code newPriority} and the maximum permitted priority of the thread's
     * {@linkplain ThreadGroup thread group}.
     *
     * The priority of a virtual thread is always {@link Thread#NORM_PRIORITY}
     * and {@code newPriority} is ignored.
     *
     * @param newPriority the new thread priority
     * @throws  IllegalArgumentException if the priority is not in the
     *          range {@code MIN_PRIORITY} to {@code MAX_PRIORITY}.
     * @see #setPriority(int)
     * @see ThreadGroup#getMaxPriority()
     */
    public final void setPriority(int newPriority) {
        if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
            throw new IllegalArgumentException();
        }
        if (!isVirtual()) {
            priority(newPriority);
        }
    }

    void priority(int newPriority) {
        ThreadGroup g = holder.group;
        if (g != null) {
            int maxPriority = g.getMaxPriority();
            if (newPriority > maxPriority) {
                newPriority = maxPriority;
            }
            setPriority0(holder.priority = newPriority);
        }
    }

    /**
     * Returns this thread's priority.
     *
     * <p> The priority of a virtual thread is always {@link Thread#NORM_PRIORITY}.
     *
     * @return  this thread's priority.
     * @see     #setPriority
     */
    public final int getPriority() {
        if (isVirtual()) {
            return Thread.NORM_PRIORITY;
        } else {
            return holder.priority;
        }
    }

    /**
     * Changes the name of this thread to be equal to the argument {@code name}.
     *
     * @implNote In the JDK Reference Implementation, if this thread is the
     * current thread, and it's a platform thread that was not attached to the
     * VM with the Java Native Interface
     * <a href="{@docRoot}/../specs/jni/invocation.html#attachcurrentthread">
     * AttachCurrentThread</a> function, then this method will set the operating
     * system thread name. This may be useful for debugging and troubleshooting
     * purposes.
     *
     * @param      name   the new name for this thread.
     *
     * @spec jni/index.html Java Native Interface Specification
     * @see        #getName
     */
    public final synchronized void setName(String name) {
        if (name == null) {
            throw new NullPointerException("name cannot be null");
        }
        this.name = name;
        if (!isVirtual() && Thread.currentThread() == this) {
            setNativeName(name);
        }
    }

    /**
     * Returns this thread's name.
     *
     * @return  this thread's name.
     * @see     #setName(String)
     */
    public final String getName() {
        return name;
    }

    /**
     * Returns the thread's thread group or {@code null} if the thread has
     * terminated.
     *
     * <p> The thread group returned for a virtual thread is the special
     * <a href="ThreadGroup.html#virtualthreadgroup"><em>ThreadGroup for
     * virtual threads</em></a>.
     *
     * @return  this thread's thread group or {@code null}
     */
    public final ThreadGroup getThreadGroup() {
        if (isTerminated()) {
            return null;
        } else {
            return isVirtual() ? virtualThreadGroup() : holder.group;
        }
    }

    /**
     * Returns an estimate of the number of {@linkplain #isAlive() live}
     * platform threads in the current thread's thread group and its subgroups.
     * Virtual threads are not included in the estimate.
     *
     * <p> The value returned is only an estimate because the number of
     * threads may change dynamically while this method traverses internal
     * data structures, and might be affected by the presence of certain
     * system threads. This method is intended primarily for debugging
     * and monitoring purposes.
     *
     * @return  an estimate of the number of live platform threads in the
     *          current thread's thread group and in any other thread group
     *          that has the current thread's thread group as an ancestor
     */
    public static int activeCount() {
        return currentThread().getThreadGroup().activeCount();
    }

    /**
     * Copies into the specified array every {@linkplain #isAlive() live}
     * platform thread in the current thread's thread group and its subgroups.
     * This method simply invokes the {@link java.lang.ThreadGroup#enumerate(Thread[])}
     * method of the current thread's thread group. Virtual threads are
     * not enumerated by this method.
     *
     * <p> An application might use the {@linkplain #activeCount activeCount}
     * method to get an estimate of how big the array should be, however
     * <i>if the array is too short to hold all the threads, the extra threads
     * are silently ignored.</i>  If it is critical to obtain every live
     * thread in the current thread's thread group and its subgroups, the
     * invoker should verify that the returned int value is strictly less
     * than the length of {@code tarray}.
     *
     * <p> Due to the inherent race condition in this method, it is recommended
     * that the method only be used for debugging and monitoring purposes.
     *
     * @param  tarray
     *         an array into which to put the list of threads
     *
     * @return  the number of threads put into the array
     */
    public static int enumerate(Thread[] tarray) {
        return currentThread().getThreadGroup().enumerate(tarray);
    }

    /**
     * Waits at most {@code millis} milliseconds for this thread to terminate.
     * A timeout of {@code 0} means to wait forever.
     * This method returns immediately, without waiting, if the thread has not
     * been {@link #start() started}.
     *
     * @implNote
     * For platform threads, the implementation uses a loop of {@code this.wait}
     * calls conditioned on {@code this.isAlive}. As a thread terminates the
     * {@code this.notifyAll} method is invoked. It is recommended that
     * applications not use {@code wait}, {@code notify}, or
     * {@code notifyAll} on {@code Thread} instances.
     *
     * @param  millis
     *         the time to wait in milliseconds
     *
     * @throws  IllegalArgumentException
     *          if the value of {@code millis} is negative
     *
     * @throws  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(long millis) throws InterruptedException {
        if (millis < 0)
            throw new IllegalArgumentException("timeout value is negative");

        if (this instanceof VirtualThread vthread) {
            if (isAlive()) {
                long nanos = MILLISECONDS.toNanos(millis);
                vthread.joinNanos(nanos);
            }
            return;
        }

        synchronized (this) {
            if (millis > 0) {
                if (isAlive()) {
                    final long startTime = System.nanoTime();
                    long delay = millis;
                    do {
                        wait(delay);
                    } while (isAlive() && (delay = millis -
                             NANOSECONDS.toMillis(System.nanoTime() - startTime)) > 0);
                }
            } else {
                while (isAlive()) {
                    wait(0);
                }
            }
        }
    }

    /**
     * Waits at most {@code millis} milliseconds plus
     * {@code nanos} nanoseconds for this thread to terminate.
     * If both arguments are {@code 0}, it means to wait forever.
     * This method returns immediately, without waiting, if the thread has not
     * been {@link #start() started}.
     *
     * @implNote
     * For platform threads, the implementation uses a loop of {@code this.wait}
     * calls conditioned on {@code this.isAlive}. As a thread terminates the
     * {@code this.notifyAll} method is invoked. It is recommended that
     * applications not use {@code wait}, {@code notify}, or
     * {@code notifyAll} on {@code Thread} instances.
     *
     * @param  millis
     *         the time to wait in milliseconds
     *
     * @param  nanos
     *         {@code 0-999999} additional nanoseconds to wait
     *
     * @throws  IllegalArgumentException
     *          if the value of {@code millis} is negative, or the value
     *          of {@code nanos} is not in the range {@code 0-999999}
     *
     * @throws  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(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 (this instanceof VirtualThread vthread) {
            if (isAlive()) {
                // convert arguments to a total in nanoseconds
                long totalNanos = MILLISECONDS.toNanos(millis);
                totalNanos += Math.min(Long.MAX_VALUE - totalNanos, nanos);
                vthread.joinNanos(totalNanos);
            }
            return;
        }

        if (nanos > 0 && millis < Long.MAX_VALUE) {
            millis++;
        }
        join(millis);
    }

    /**
     * Waits for this thread to terminate.
     *
     * <p> An invocation of this method behaves in exactly the same
     * way as the invocation
     *
     * <blockquote>
     * {@linkplain #join(long) join}{@code (0)}
     * </blockquote>
     *
     * @throws  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);
    }

    /**
     * Waits for this thread to terminate for up to the given waiting duration.
     *
     * <p> This method does not wait if the duration to wait is less than or
     * equal to zero. In this case, the method just tests if the thread has
     * terminated.
     *
     * @param   duration
     *          the maximum duration to wait
     *
     * @return  {@code true} if the thread has terminated, {@code false} if the
     *          thread has not terminated
     *
     * @throws  InterruptedException
     *          if the current thread is interrupted while waiting.
     *          The <i>interrupted status</i> of the current thread is cleared
     *          when this exception is thrown.
     *
     * @throws  IllegalThreadStateException
     *          if this thread has not been started.
     *
     * @since 19
     */
    public final boolean join(Duration duration) throws InterruptedException {
        long nanos = NANOSECONDS.convert(duration); // MAX_VALUE if > 292 years

        Thread.State state = threadState();
        if (state == State.NEW)
            throw new IllegalThreadStateException("Thread not started");
        if (state == State.TERMINATED)
            return true;
        if (nanos <= 0)
            return false;

        if (this instanceof VirtualThread vthread) {
            return vthread.joinNanos(nanos);
        }

        // convert to milliseconds
        long millis = MILLISECONDS.convert(nanos, NANOSECONDS);
        if (nanos > NANOSECONDS.convert(millis, MILLISECONDS)) {
            millis += 1L;
        }
        join(millis);
        return isTerminated();
    }

    /**
     * Prints a stack trace of the current thread to the standard error stream.
     * This method is useful for debugging.
     */
    public static void dumpStack() {
        new Exception("Stack trace").printStackTrace();
    }

    /**
     * Marks this thread as either a <i>daemon</i> or <i>non-daemon</i> thread.
     * The <a href="Runtime.html#shutdown">shutdown sequence</a> begins when all
     * started non-daemon threads have terminated.
     *
     * <p> The daemon status of a virtual thread is always {@code true} and cannot be
     * changed by this method to {@code false}.
     *
     * <p> This method must be invoked before the thread is started. The behavior
     * of this method when the thread has terminated is not specified.
     *
     * @param  on
     *         if {@code true}, marks this thread as a daemon thread
     *
     * @throws  IllegalArgumentException
     *          if this is a virtual thread and {@code on} is false
     * @throws  IllegalThreadStateException
     *          if this thread is {@linkplain #isAlive alive}
     */
    public final void setDaemon(boolean on) {
        if (isVirtual() && !on)
            throw new IllegalArgumentException("'false' not legal for virtual threads");
        if (isAlive())
            throw new IllegalThreadStateException();
        if (!isVirtual())
            daemon(on);
    }

    void daemon(boolean on) {
        holder.daemon = on;
    }

    /**
     * Tests if this thread is a daemon thread.
     * The daemon status of a virtual thread is always {@code true}.
     *
     * @return  {@code true} if this thread is a daemon thread;
     *          {@code false} otherwise.
     * @see     #setDaemon(boolean)
     */
    public final boolean isDaemon() {
        if (isVirtual()) {
            return true;
        } else {
            return holder.daemon;
        }
    }

    /**
     * Does nothing.
     *
     * @deprecated This method originally determined if the currently running
     * thread had permission to modify this thread. This method was only useful
     * in conjunction with {@linkplain SecurityManager the Security Manager},
     * which is no longer supported. There is no replacement for the Security
     * Manager or this method.
     */
    @Deprecated(since="17", forRemoval=true)
    public final void checkAccess() { }

    /**
     * Returns a string representation of this thread. The string representation
     * will usually include the thread's {@linkplain #threadId() identifier} and
     * name. The default implementation for platform threads includes the thread's
     * identifier, name, priority, and the name of the thread group.
     *
     * @return  a string representation of this thread.
     */
    public String toString() {
        StringBuilder sb = new StringBuilder("Thread[#");
        sb.append(threadId());
        sb.append(",");
        sb.append(getName());
        sb.append(",");
        sb.append(getPriority());
        sb.append(",");
        ThreadGroup group = getThreadGroup();
        if (group != null)
            sb.append(group.getName());
        sb.append("]");
        return sb.toString();
    }

    /**
     * Returns the context {@code ClassLoader} for this thread.
     * The context {@code ClassLoader} may be set by the creator of the thread
     * for use by code running in this thread when loading classes and resources.
     * If not {@linkplain #setContextClassLoader set}, the default is to inherit
     * the context class loader from the parent thread.
     *
     * <p> The context {@code ClassLoader} of the primordial thread is typically
     * set to the class loader used to load the application.
     *
     * @return  the context {@code ClassLoader} for this thread, or {@code null}
     *          indicating the system class loader (or, failing that, the
     *          bootstrap class loader)
     *
     * @since 1.2
     */
    public ClassLoader getContextClassLoader() {
        return contextClassLoader;
    }

    /**
     * Sets the context {@code ClassLoader} for this thread.
     *
     * <p> The context {@code ClassLoader} may be set by the creator of the thread
     * for use by code running in this thread when loading classes and resources.
     *
     * @param  cl
     *         the context ClassLoader for this Thread, or null  indicating the
     *         system class loader (or, failing that, the bootstrap class loader)
     *
     * @since 1.2
     */
    public void setContextClassLoader(ClassLoader cl) {
        contextClassLoader = cl;
    }

    /**
     * Returns {@code true} 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
     * @return {@code true} if the current thread holds the monitor lock on
     *         the specified object.
     * @since 1.4
     */
    public static native boolean holdsLock(Object obj);

    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, has started but has not yet been
     * scheduled to run by the system, 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>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 {@code StackTraceElement},
     * each represents one stack frame.
     *
     * @see Throwable#getStackTrace
     * @since 1.5
     */
    public StackTraceElement[] getStackTrace() {
        if (this != Thread.currentThread()) {
            // 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[] stackTrace = asyncGetStackTrace();
            return (stackTrace != null) ? stackTrace : EMPTY_STACK_TRACE;
        } else {
            return (new Exception()).getStackTrace();
        }
    }

    /**
     * Returns an array of stack trace elements representing the stack dump of
     * this thread. Returns null if the stack trace cannot be obtained. In
     * the default implementation, null is returned if the thread is a virtual
     * thread that is not mounted or the thread is a platform thread that has
     * terminated.
     */
    StackTraceElement[] asyncGetStackTrace() {
        Object stackTrace = getStackTrace0();
        if (stackTrace == null) {
            return null;
        }
        StackTraceElement[] stes = (StackTraceElement[]) stackTrace;
        if (stes.length == 0) {
            return null;
        } else {
            return StackTraceElement.of(stes);
        }
    }

    private native Object getStackTrace0();

    /**
     * Returns a map of stack traces for all live platform threads. The map
     * does not include virtual threads.
     * The map keys are threads and each map value is an array of
     * {@code StackTraceElement} that represents the stack dump
     * of the corresponding {@code Thread}.
     * 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.
     *
     * @return a {@code Map} from {@code Thread} to an array of
     * {@code StackTraceElement} that represents the stack trace of
     * the corresponding thread.
     *
     * @see #getStackTrace
     * @see Throwable#getStackTrace
     *
     * @since 1.5
     */
    public static Map<Thread, StackTraceElement[]> getAllStackTraces() {
        // Get a snapshot of the list of all threads
        Thread[] threads = getThreads();
        StackTraceElement[][] traces = dumpThreads(threads);
        Map<Thread, StackTraceElement[]> m = HashMap.newHashMap(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;
    }

    /**
     * Return an array of all live threads.
     */
    static Thread[] getAllThreads() {
        return getThreads();
    }

    private static native StackTraceElement[][] dumpThreads(Thread[] threads);
    private static native Thread[] getThreads();

    /**
     * Returns the identifier of this Thread.  The thread ID is a positive
     * {@code long} number generated when this thread was created.
     * The thread ID is unique and remains unchanged during its lifetime.
     *
     * @return this thread's ID
     *
     * @deprecated This method is not final and may be overridden to return a
     * value that is not the thread ID. Use {@link #threadId()} instead.
     *
     * @since 1.5
     */
    @Deprecated(since="19")
    public long getId() {
        return threadId();
    }

    /**
     * Returns the identifier of this Thread.  The thread ID is a positive
     * {@code long} number generated when this thread was created.
     * The thread ID is unique and remains unchanged during its lifetime.
     *
     * @return this thread's ID
     * @since 19
     */
    public final long threadId() {
        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 {@code Object.wait()}
         * on an object is waiting for another thread to call
         * {@code Object.notify()} or {@code Object.notifyAll()} on
         * that object. A thread that has called {@code Thread.join()}
         * 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() {
        return threadState();
    }

    /**
     * Returns the state of this thread.
     * This method can be used instead of getState as getState is not final and
     * so can be overridden to run arbitrary code.
     */
    State threadState() {
        return jdk.internal.misc.VM.toThreadState(holder.threadStatus);
    }

    /**
     * Returns true if the thread has terminated.
     */
    boolean isTerminated() {
        return threadState() == State.TERMINATED;
    }

    /**
     * Interface for handlers invoked when a {@code Thread} 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
     * {@code UncaughtExceptionHandler} using
     * {@link #getUncaughtExceptionHandler} and will invoke the handler's
     * {@code uncaughtException} method, passing the thread and the
     * exception as arguments.
     * If a thread has not had its {@code UncaughtExceptionHandler}
     * explicitly set, then its {@code ThreadGroup} object acts as its
     * {@code UncaughtExceptionHandler}. If the {@code ThreadGroup} 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
     */
    @FunctionalInterface
    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
     * {@code uncaughtException} method, then the default handler's
     * {@code uncaughtException} 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 {@code ThreadGroup} object, as that could cause
     * infinite recursion.
     *
     * @param ueh the object to use as the default uncaught exception handler.
     * If {@code null} then there is no default handler.
     *
     * @see #setUncaughtExceptionHandler
     * @see #getUncaughtExceptionHandler
     * @see ThreadGroup#uncaughtException
     * @since 1.5
     */
    public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler ueh) {
        defaultUncaughtExceptionHandler = ueh;
    }

    /**
     * Returns the default handler invoked when a thread abruptly terminates
     * due to an uncaught exception. If the returned value is {@code null},
     * there is no default.
     * @since 1.5
     * @see #setDefaultUncaughtExceptionHandler
     * @return the default uncaught exception handler for all threads
     */
    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
     * {@code ThreadGroup} object is returned, unless this thread
     * has terminated, in which case {@code null} is returned.
     * @since 1.5
     * @return the uncaught exception handler for this thread
     */
    public UncaughtExceptionHandler getUncaughtExceptionHandler() {
        if (isTerminated()) {
            // uncaughtExceptionHandler may be set to null after thread terminates
            return null;
        } else {
            UncaughtExceptionHandler ueh = uncaughtExceptionHandler;
            return (ueh != null) ? ueh : getThreadGroup();
        }
    }

    /**
     * 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 {@code ThreadGroup}
     * object acts as its handler.
     * @param ueh the object to use as this thread's uncaught exception
     * handler. If {@code null} then this thread has no explicit handler.
     * @see #setDefaultUncaughtExceptionHandler
     * @see ThreadGroup#uncaughtException
     * @since 1.5
     */
    public void setUncaughtExceptionHandler(UncaughtExceptionHandler ueh) {
        uncaughtExceptionHandler(ueh);
    }

    void uncaughtExceptionHandler(UncaughtExceptionHandler ueh) {
        uncaughtExceptionHandler = ueh;
    }

    /**
     * Dispatch an uncaught exception to the handler. This method is
     * called when a thread terminates with an exception.
     */
    void dispatchUncaughtException(Throwable e) {
        getUncaughtExceptionHandler().uncaughtException(this, e);
    }

    /**
     * Holder class for constants.
     */
    private static class Constants {
        // Thread group for virtual threads.
        static final ThreadGroup VTHREAD_GROUP;

        static {
            ThreadGroup root = Thread.currentCarrierThread().getThreadGroup();
            for (ThreadGroup p; (p = root.getParent()) != null; ) {
                root = p;
            }
            VTHREAD_GROUP = new ThreadGroup(root, "VirtualThreads", MAX_PRIORITY, false);
        }
    }

    /**
     * Returns the special ThreadGroup for virtual threads.
     */
    static ThreadGroup virtualThreadGroup() {
        return Constants.VTHREAD_GROUP;
    }

    // The following three initially uninitialized fields are exclusively
    // managed by class java.util.concurrent.ThreadLocalRandom. These
    // fields are used to build the high-performance PRNGs in the
    // concurrent code.

    /** The current seed for a ThreadLocalRandom */
    long threadLocalRandomSeed;

    /** Probe hash value; nonzero if threadLocalRandomSeed initialized */
    int threadLocalRandomProbe;

    /** Secondary seed isolated from public ThreadLocalRandom sequence */
    int threadLocalRandomSecondarySeed;

    /** The thread container that this thread is in */
    private @Stable ThreadContainer container;
    ThreadContainer threadContainer() {
        return container;
    }
    void setThreadContainer(ThreadContainer container) {
        // assert this.container == null;
        this.container = container;
    }

    /** The top of this stack of stackable scopes owned by this thread */
    private volatile StackableScope headStackableScopes;
    StackableScope headStackableScopes() {
        return headStackableScopes;
    }
    static void setHeadStackableScope(StackableScope scope) {
        currentThread().headStackableScopes = scope;
    }

    /* Some private helper methods */
    private native void setPriority0(int newPriority);
    private native void interrupt0();
    private static native void clearInterruptEvent();
    private native void setNativeName(String name);

    // The address of the next thread identifier, see ThreadIdentifiers.
    private static native long getNextThreadIdOffset();
}
