Path: blob/master/jcl/src/java.base/share/classes/java/lang/Thread.java
12513 views
/*[INCLUDE-IF Sidecar18-SE & !OPENJDK_THREAD_SUPPORT]*/1/*******************************************************************************2* Copyright (c) 1998, 2022 IBM Corp. and others3*4* This program and the accompanying materials are made available under5* the terms of the Eclipse Public License 2.0 which accompanies this6* distribution and is available at https://www.eclipse.org/legal/epl-2.0/7* or the Apache License, Version 2.0 which accompanies this distribution and8* is available at https://www.apache.org/licenses/LICENSE-2.0.9*10* This Source Code may also be made available under the following11* Secondary Licenses when the conditions for such availability set12* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU13* General Public License, version 2 with the GNU Classpath14* Exception [1] and GNU General Public License, version 2 with the15* OpenJDK Assembly Exception [2].16*17* [1] https://www.gnu.org/software/classpath/license.html18* [2] http://openjdk.java.net/legal/assembly-exception.html19*20* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception21*******************************************************************************/22package java.lang;2324import java.util.Map;25import java.security.AccessControlContext;26import java.security.AccessController;27import java.security.PrivilegedAction;28/*[IF Sidecar18-SE-OpenJ9]*/29import jdk.internal.misc.TerminatingThreadLocal;30/*[ENDIF] Sidecar18-SE-OpenJ9 */31import sun.security.util.SecurityConstants;32/*[IF JAVA_SPEC_VERSION >= 11]*/33import java.io.FileDescriptor;34import java.nio.charset.Charset;35import java.util.Properties;36import jdk.internal.reflect.CallerSensitive;37/*[ELSE] JAVA_SPEC_VERSION >= 11 */38import sun.reflect.CallerSensitive;39/*[ENDIF] JAVA_SPEC_VERSION >= 11 */40import java.lang.reflect.Method;41import sun.nio.ch.Interruptible;4243/**44* A Thread is a unit of concurrent execution in Java. It has its own call stack45* for methods being called and their parameters. Threads in the same VM interact and46* synchronize by the use of shared Objects and monitors associated with these objects.47* Synchronized methods and part of the API in Object also allow Threads to cooperate.48*49* When a Java program starts executing there is an implicit Thread (called "main")50* which is automatically created by the VM. This Thread belongs to a ThreadGroup51* (also called "main") which is automatically created by the bootstrap sequence by52* the VM as well.53*54* @see java.lang.Object55* @see java.lang.ThreadGroup56*/57public class Thread implements Runnable {5859/* Maintain thread shape in all configs */6061/**62* The maximum priority value for a Thread.63*/64public final static int MAX_PRIORITY = 10; // Maximum allowed priority for a thread65/**66* The minimum priority value for a Thread.67*/68public final static int MIN_PRIORITY = 1; // Minimum allowed priority for a thread69/**70* The default priority value for a Thread.71*/72public final static int NORM_PRIORITY = 5; // Normal priority for a thread73/*[PR 97331] Initial thread name should be Thread-0 */74private static int createCount = -1; // Used internally to compute Thread names that comply with the Java specification75/*[PR 122459] LIR646 - Remove use of generic object for synchronization */76private static final class TidLock {77TidLock() {}78}79private static Object tidLock = new TidLock();80private static long tidCount = 1;81private static final int NANOS_MAX = 999999; // Max value for nanoseconds parameter to sleep and join82private static final int INITIAL_LOCAL_STORAGE_CAPACITY = 5; // Initial number of local storages when the Thread is created83static final long NO_REF = 0; // Symbolic constant, no threadRef assigned or already cleaned up8485// Instance variables86private long threadRef; // Used by the VM87long stackSize = 0;88/*[IF JAVA_SPEC_VERSION >= 14]*/89/* deadInterrupt tracks the thread interrupt state when threadRef has no reference (ie thread is not alive).90* Note that this value need not be updated while the thread is running since the interrupt state will be91* tracked by the vm during that time. Because of this the value should not be used over calling92* isInterrupted() or interrupted().93*/94private volatile boolean deadInterrupt;95/*[ENDIF] JAVA_SPEC_VERSION >= 14 */96private volatile boolean started; // If !isAlive(), tells if Thread died already or hasn't even started97private String name; // The Thread's name98private int priority = NORM_PRIORITY; // The Thread's current priority99private boolean isDaemon; // Tells if the Thread is a daemon thread or not.100101ThreadGroup group; // A Thread belongs to exactly one ThreadGroup102private Runnable runnable; // Target (optional) runnable object103private boolean stopCalled = false; // Used by the VM104/*[PR 1FENTZW]*/105private ClassLoader contextClassLoader; // Used to find classes and resources in this Thread106ThreadLocal.ThreadLocalMap threadLocals;107private java.security.AccessControlContext inheritedAccessControlContext;108109/*[PR 96127]*/110/*[PR 122459] LIR646 - Remove use of generic object for synchronization */111private static final class ThreadLock {}112private Object lock = new ThreadLock();113114ThreadLocal.ThreadLocalMap inheritableThreadLocals;115private volatile Interruptible blockOn;116117int threadLocalsIndex;118int inheritableThreadLocalsIndex;119120/*[PR 113602] Thread fields should be volatile */121private volatile UncaughtExceptionHandler exceptionHandler;122private long tid;123124volatile Object parkBlocker;125126private static ThreadGroup systemThreadGroup; // Assigned by the vm127private static ThreadGroup mainGroup; // ThreadGroup where the "main" Thread starts128129/*[PR 113602] Thread fields should be volatile */130private volatile static UncaughtExceptionHandler defaultExceptionHandler;131132/*[PR CMVC 196696] Build error:java.lang.Thread need extra fields */133long threadLocalRandomSeed;134int threadLocalRandomProbe;135int threadLocalRandomSecondarySeed;136137private static final StackTraceElement[] EMPTY_STACK_TRACE = new StackTraceElement[0];138139/**140* Constructs a new Thread with no runnable object and a newly generated name.141* The new Thread will belong to the same ThreadGroup as the Thread calling142* this constructor.143*144* @see java.lang.ThreadGroup145*/146public Thread() {147this(null, null, newName(), null, true);148}149150/**151*152* Private constructor to be used by the VM for the threads attached through JNI.153* They already have a running thread with no associated Java Thread, so this is154* where the binding is done.155*156* @param vmName Name for the Thread being created (or null to auto-generate a name)157* @param vmThreadGroup ThreadGroup for the Thread being created (or null for main threadGroup)158* @param vmPriority Priority for the Thread being created159* @param vmIsDaemon Indicates whether or not the Thread being created is a daemon thread160*161* @see java.lang.ThreadGroup162*/163private Thread(String vmName, Object vmThreadGroup, int vmPriority, boolean vmIsDaemon) {164super();165166String threadName = (vmName == null) ? newName() : vmName;167/*[IF JAVA_SPEC_VERSION < 15]*/168setNameImpl(threadRef, threadName);169/*[ENDIF] JAVA_SPEC_VERSION < 15 */170name = threadName;171172isDaemon = vmIsDaemon;173priority = vmPriority; // If we called setPriority(), it would have to be after setting the ThreadGroup (further down),174// because of the checkAccess() call (which requires the ThreadGroup set). However, for the main175// Thread or JNI-C attached Threads we just trust the value the VM is passing us, and just assign.176177ThreadGroup threadGroup = null;178boolean booting = false;179if (mainGroup == null) { // only occurs during bootstrap180booting = true;181/*[PR CMVC 71192] Initialize the "main" thread group without calling checkAccess() */182mainGroup = new ThreadGroup(systemThreadGroup);183} else {184/*[IF JAVA_SPEC_VERSION >= 15]*/185setNameImpl(threadRef, threadName);186/*[ENDIF] JAVA_SPEC_VERSION >= 15 */187}188threadGroup = vmThreadGroup == null ? mainGroup : (ThreadGroup)vmThreadGroup;189190/*[PR 1FEVFSU] The rest of the configuration/initialization is shared between this constructor and the public one */191initialize(booting, threadGroup, null, null, true); // no parent Thread192/*[PR 115667, CMVC 94448] In 1.5 and CDC/Foundation 1.1, thread is added to ThreadGroup when started */193this.group.add(this);194195/*[PR 100718] Initialize System.in after the main thread */196if (booting) {197/*[IF JAVA_SPEC_VERSION >= 15]*/198/* JDK15+ native method binding uses java.lang.ClassLoader.findNative():bootstrapClassLoader.nativelibs.find(entryName)199* to lookup native address when not found within systemClassLoader native libraries.200* This requires bootstrapClassLoader is initialized via initialize(booting, threadGroup, null, null, true) above before201* invoking a native method not present within systemClassLoader native libraries such as following setNameImpl modified202* via JVMTI agent SetNativeMethodPrefix (https://github.com/eclipse-openj9/openj9/issues/11181).203* After bootstrapClassLoader initialization, setNameImpl can be invoked before initialize() to set thread name earlier.204*/205setNameImpl(threadRef, threadName);206/*[ENDIF] JAVA_SPEC_VERSION >= 15 */207System.completeInitialization();208}209}210211/*212* Called after everything else is initialized.213*/214void completeInitialization() {215// Get the java.system.class.loader216/*[PR CMVC 99755] Implement -Djava.system.class.loader option */217contextClassLoader = ClassLoader.getSystemClassLoader();218/*[IF Sidecar19-SE]*/219jdk.internal.misc.VM.initLevel(4);220/*[ELSE]*/ // Sidecar19-SE221sun.misc.VM.booted();222/*[ENDIF]*/ // Sidecar19-SE223/*[IF Sidecar19-SE|Sidecar18-SE-OpenJ9]*/224System.startSNMPAgent();225/*[ENDIF]*/ // Sidecar19-SE|Sidecar18-SE-OpenJ9226227/*[IF JAVA_SPEC_VERSION >= 11] */228/* Although file.encoding is used to set the default Charset, some Charset's are not available229* in the java.base module and so are not used at startup. There are additional Charset's in the230* jdk.charsets module, which is only loaded later. This means the default Charset may not be the231* same as file.encoding. Now that all modules and Charset's are available, check if the desired232* encodings can be used for System.err and System.out.233*/234Properties props = System.internalGetProperties();235// If the sun.stderr.encoding was already set in System, don't change the encoding236if (!System.hasSetErrEncoding()) {237Charset stderrCharset = System.getCharset(props.getProperty("sun.stderr.encoding"), true); //$NON-NLS-1$238if (stderrCharset != null) {239System.err.flush();240System.setErr(System.createConsole(FileDescriptor.err, stderrCharset));241}242}243244// If the sun.stdout.encoding was already set in System, don't change the encoding245if (!System.hasSetOutEncoding()) {246Charset stdoutCharset = System.getCharset(props.getProperty("sun.stdout.encoding"), true); //$NON-NLS-1$247if (stdoutCharset != null) {248System.out.flush();249System.setOut(System.createConsole(FileDescriptor.out, stdoutCharset));250}251}252/*[ENDIF] JAVA_SPEC_VERSION >= 11 */253}254255/**256* Constructs a new Thread with a runnable object and a newly generated name.257* The new Thread will belong to the same ThreadGroup as the Thread calling258* this constructor.259*260* @param runnable a java.lang.Runnable whose method <code>run</code> will be executed by the new Thread261*262* @see java.lang.ThreadGroup263* @see java.lang.Runnable264*/265public Thread(Runnable runnable) {266this(null, runnable, newName(), null, true);267}268269/*270* [PR CMVC 199693] Prevent a trusted method chain attack.271*/272273/**274* Constructs a new Thread with a runnable object and a newly generated name,275* setting the specified AccessControlContext.276* The new Thread will belong to the same ThreadGroup as the Thread calling277* this constructor.278*279* @param runnable a java.lang.Runnable whose method <code>run</code> will be executed by the new Thread280* @param acc the AccessControlContext to use for the Thread281*282* @see java.lang.ThreadGroup283* @see java.lang.Runnable284*/285Thread(Runnable runnable, AccessControlContext acc) {286this(null, runnable, newName(), acc, true);287}288289/**290* Constructs a new Thread with a runnable object and name provided.291* The new Thread will belong to the same ThreadGroup as the Thread calling292* this constructor.293*294* @param runnable a java.lang.Runnable whose method <code>run</code> will be executed by the new Thread295* @param threadName Name for the Thread being created296*297* @see java.lang.ThreadGroup298* @see java.lang.Runnable299*/300public Thread(Runnable runnable, String threadName) {301this(null, runnable, threadName, null, true);302}303304305/**306* Constructs a new Thread with no runnable object and the name provided.307* The new Thread will belong to the same ThreadGroup as the Thread calling308* this constructor.309*310* @param threadName Name for the Thread being created311*312* @see java.lang.ThreadGroup313* @see java.lang.Runnable314*/315public Thread(String threadName) {316this(null, null, threadName, null, true);317}318319/**320* Constructs a new Thread with a runnable object and a newly generated name.321* The new Thread will belong to the ThreadGroup passed as parameter.322*323* @param group ThreadGroup to which the new Thread will belong324* @param runnable a java.lang.Runnable whose method <code>run</code> will be executed by the new Thread325*326* @exception SecurityException327* if <code>group.checkAccess()</code> fails with a SecurityException328* @exception IllegalThreadStateException329* if <code>group.destroy()</code> has already been done330*331* @see java.lang.ThreadGroup332* @see java.lang.Runnable333* @see java.lang.SecurityException334* @see java.lang.SecurityManager335*/336public Thread(ThreadGroup group, Runnable runnable) {337this(group, runnable, newName(), null, true);338}339340/**341* Constructs a new Thread with a runnable object, the given name and342* belonging to the ThreadGroup passed as parameter.343*344* @param group ThreadGroup to which the new Thread will belong345* @param runnable a java.lang.Runnable whose method <code>run</code> will be executed by the new Thread346* @param threadName Name for the Thread being created347* @param stack Platform dependent stack size348*349* @exception SecurityException350* if <code>group.checkAccess()</code> fails with a SecurityException351* @exception IllegalThreadStateException352* if <code>group.destroy()</code> has already been done353*354* @since 1.4355*356* @see java.lang.ThreadGroup357* @see java.lang.Runnable358* @see java.lang.SecurityException359* @see java.lang.SecurityManager360*/361public Thread(ThreadGroup group, Runnable runnable, String threadName, long stack) {362this(group, runnable, threadName, null, true);363this.stackSize = stack;364}365366/*[IF Sidecar19-SE]*/367/**368* Constructs a new Thread with a runnable object, the given name, the thread stack size,369* the flag to inherit initial values for inheritable thread-local variables and370* belonging to the ThreadGroup passed as parameter.371*372* @param group ThreadGroup to which the new Thread will belong373* @param runnable A java.lang.Runnable whose method <code>run</code> will be executed by the new Thread374* @param threadName Name for the Thread being created375* @param stack Platform dependent stack size376* @param inheritThreadLocals A boolean indicating whether to inherit initial values for inheritable thread-local variables.377*378* @exception SecurityException379* if <code>group.checkAccess()</code> fails with a SecurityException380* @exception IllegalThreadStateException381* if <code>group.destroy()</code> has already been done382*383*/384public Thread(ThreadGroup group, Runnable runnable, String threadName, long stack, boolean inheritThreadLocals) {385this(group, runnable, threadName, null, inheritThreadLocals);386this.stackSize = stack;387}388/*[ENDIF]*/389390/**391* Constructs a new Thread with a runnable object, the given name and392* belonging to the ThreadGroup passed as parameter.393*394* @param group ThreadGroup to which the new Thread will belong395* @param runnable a java.lang.Runnable whose method <code>run</code> will be executed by the new Thread396* @param threadName Name for the Thread being created397*398* @exception SecurityException399* if <code>group.checkAccess()</code> fails with a SecurityException400* @exception IllegalThreadStateException401* if <code>group.destroy()</code> has already been done402*403* @see java.lang.ThreadGroup404* @see java.lang.Runnable405* @see java.lang.SecurityException406* @see java.lang.SecurityManager407*/408public Thread(ThreadGroup group, Runnable runnable, String threadName) {409this(group, runnable, threadName, null, true);410}411412Thread(Runnable runnable, String threadName, boolean isSystemThreadGroup, boolean inheritThreadLocals, boolean isDaemon, ClassLoader contextClassLoader) {413this(isSystemThreadGroup ? systemThreadGroup : null, runnable, threadName, null, inheritThreadLocals);414this.isDaemon = isDaemon;415this.contextClassLoader = contextClassLoader;416}417418private Thread(ThreadGroup group, Runnable runnable, String threadName, AccessControlContext acc, boolean inheritThreadLocals) {419super();420/*[PR 1FEVFSU] Re-arrange method so that common code to this constructor and the private one the VM calls can be put in a separate method */421/*[PR 1FIGT59] name cannot be null*/422if (threadName==null) throw new NullPointerException();423this.name = threadName; // We avoid the public API 'setName', since it does redundant work (checkAccess)424this.runnable = runnable; // No API available here, so just direct access to inst. var.425Thread currentThread = currentThread();426427this.isDaemon = currentThread.isDaemon(); // We avoid the public API 'setDaemon', since it does redundant work (checkAccess)428429/*[PR 1FEO92F] (dup of 1FC0TRN) */430if (group == null) {431@SuppressWarnings("removal")432SecurityManager currentManager = System.getSecurityManager();433// if there is a security manager...434if (currentManager != null)435// Ask SecurityManager for ThreadGroup436group = currentManager.getThreadGroup();437}438/*[PR 94235]*/439if (group == null)440// Same group as Thread that created us441group = currentThread.getThreadGroup();442443444/*[PR 1FEVFSU] The rest of the configuration/initialization is shared between this constructor and the private one */445initialize(false, group, currentThread, acc, inheritThreadLocals);446447setPriority(currentThread.getPriority()); // In this case we can call the public API according to the spec - 20.20.10448}449450/**451* Initialize the thread according to its parent Thread and the ThreadGroup452* where it should be added.453*454* @param booting Indicates if the JVM is booting up, i.e. if the main thread is being attached455* @param threadGroup ThreadGroup The ThreadGroup to which the receiver is being added.456* @param parentThread Thread The creator Thread from which to inherit some values like local storage, etc.457* If null, the receiver is either the main Thread or a JNI-C attached Thread.458* @param acc The AccessControlContext. If null, use the current context459* @param inheritThreadLocals A boolean indicating whether to inherit initial values for inheritable thread-local variables.460*/461private void initialize(boolean booting, ThreadGroup threadGroup, Thread parentThread, AccessControlContext acc, boolean inheritThreadLocals) {462synchronized (tidLock) {463tid = tidCount++;464}465466/*[PR 96408]*/467this.group = threadGroup;468469470if (booting) {471System.afterClinitInitialization();472}473474475// initialize the thread local storage before making other calls476if (parentThread != null) { // Non-main thread477if (inheritThreadLocals && (null != parentThread.inheritableThreadLocals)) {478inheritableThreadLocals = ThreadLocal.createInheritedMap(parentThread.inheritableThreadLocals);479}480481/*[PR CMVC 90230] enableContextClassLoaderOverride check added in 1.5 */482@SuppressWarnings("removal")483final SecurityManager sm = System.getSecurityManager();484final Class<?> implClass = getClass();485final Class<?> thisClass = Thread.class;486if ((sm != null) && (implClass != thisClass)) {487boolean override = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {488@Override489public Boolean run() {490try {491Method method = implClass.getMethod("getContextClassLoader"); //$NON-NLS-1$492if (method.getDeclaringClass() != thisClass) {493return Boolean.TRUE;494}495} catch (NoSuchMethodException e) {496}497try {498Method method = implClass.getDeclaredMethod("setContextClassLoader", ClassLoader.class); //$NON-NLS-1$499if (method.getDeclaringClass() != thisClass) {500return Boolean.TRUE;501}502} catch (NoSuchMethodException e) {503}504return Boolean.FALSE;505}506}).booleanValue();507if (override) {508sm.checkPermission(com.ibm.oti.util.RuntimePermissions.permissionEnableContextClassLoaderOverride);509}510}511// By default a Thread "inherits" the context ClassLoader from its creator512/*[PR CMVC 90230] behavior change in 1.5, call getContextClassLoader() instead of accessing field */513contextClassLoader = parentThread.getContextClassLoader();514} else { // no parent: main thread, or one attached through JNI-C515/*[PR 111189] Do not initialize ClassLoaders in a static initializer */516if (booting) {517// Preload and initialize the JITHelpers class518try {519Class.forName("com.ibm.jit.JITHelpers"); //$NON-NLS-1$520} catch(ClassNotFoundException e) {521// Continue silently if the class can't be loaded and initialized for some reason,522// The JIT will tolerate this.523}524525// Explicitly initialize ClassLoaders, so ClassLoader methods (such as526// ClassLoader.callerClassLoader) can be used before System is initialized527ClassLoader.initializeClassLoaders();528}529// Just set the context class loader530contextClassLoader = ClassLoader.getSystemClassLoader();531}532533threadGroup.checkAccess();534/*[PR 115667, CMVC 94448] In 1.5 and CDC/Foundation 1.1, thread is added to ThreadGroup when started */535threadGroup.checkNewThread(this);536537inheritedAccessControlContext = acc == null ? AccessController.getContext() : acc;538}539540/**541* Constructs a new Thread with no runnable object, the given name and542* belonging to the ThreadGroup passed as parameter.543*544* @param group ThreadGroup to which the new Thread will belong545* @param threadName Name for the Thread being created546*547* @exception SecurityException548* if <code>group.checkAccess()</code> fails with a SecurityException549* @exception IllegalThreadStateException550* if <code>group.destroy()</code> has already been done551*552* @see java.lang.ThreadGroup553* @see java.lang.SecurityException554* @see java.lang.SecurityManager555*/556public Thread(ThreadGroup group, String threadName) {557this(group, null, threadName, null, true);558}559560/**561* Returns how many threads are active in the <code>ThreadGroup</code>562* which the current thread belongs to.563*564* @return Number of Threads565*/566public static int activeCount(){567/*[PR CMVC 93001] changed in 1.5 to only count active threads */568return currentThread().getThreadGroup().activeCount();569}570571572/**573* This method is used for operations that require approval from574* a SecurityManager. If there's none installed, this method is a no-op.575* If there's a SecurityManager installed , <code>checkAccess(Ljava.lang.Thread;)</code>576* is called for that SecurityManager.577*578* @see java.lang.SecurityException579* @see java.lang.SecurityManager580*/581/*[IF JAVA_SPEC_VERSION >= 17]*/582@Deprecated(since="17", forRemoval=true)583/*[ENDIF] JAVA_SPEC_VERSION >= 17 */584public final void checkAccess() {585@SuppressWarnings("removal")586SecurityManager currentManager = System.getSecurityManager();587if (currentManager != null) currentManager.checkAccess(this);588}589590/**591* Returns the number of stack frames in this thread.592*593* @return Number of stack frames594*595/*[IF JAVA_SPEC_VERSION >= 14]596* @exception UnsupportedOperationException597/*[ENDIF] JAVA_SPEC_VERSION >= 14598*599* @deprecated The semantics of this method are poorly defined and it uses the deprecated suspend() method.600*/601/*[IF JAVA_SPEC_VERSION >= 11]*/602@Deprecated(forRemoval=true, since="1.2")603/*[ELSE] JAVA_SPEC_VERSION >= 11 */604@Deprecated605/*[ENDIF] JAVA_SPEC_VERSION >= 11 */606public int countStackFrames() {607/*[IF JAVA_SPEC_VERSION >= 14]*/608throw new UnsupportedOperationException();609/*[ELSE] JAVA_SPEC_VERSION >= 14 */610return 0;611/*[ENDIF] JAVA_SPEC_VERSION >= 14 */612}613614/**615* Answers the instance of Thread that corresponds to the running Thread616* which calls this method.617*618* @return a java.lang.Thread corresponding to the code that called <code>currentThread()</code>619*/620public static native Thread currentThread();621622/*[IF JAVA_SPEC_VERSION < 11]*/623/**624* Destroys the receiver without any monitor cleanup. Not implemented.625*626* @deprecated May cause deadlocks.627*/628/*[IF Sidecar19-SE]*/629@Deprecated(forRemoval=true, since="1.5")630/*[ELSE]*/631@Deprecated632/*[ENDIF]*/633public void destroy() {634/*[PR 121318] Should throw NoSuchMethodError */635throw new NoSuchMethodError();636}637/*[ENDIF] JAVA_SPEC_VERSION < 11 */638639/**640* Prints a text representation of the stack for this Thread.641*/642public static void dumpStack() {643new Throwable().printStackTrace();644}645646/**647* Copies an array with all Threads which are in the same ThreadGroup as648* the receiver - and subgroups - into the array <code>threads</code>649* passed as parameter. If the array passed as parameter is too small no650* exception is thrown - the extra elements are simply not copied.651*652* @param threads array into which the Threads will be copied653*654* @return How many Threads were copied over655*656* @exception SecurityException657* if the installed SecurityManager fails <code>checkAccess(Ljava.lang.Thread;)</code>658*659* @see java.lang.SecurityException660* @see java.lang.SecurityManager661*/662public static int enumerate(Thread[] threads) {663return currentThread().getThreadGroup().enumerate(threads, true);664}665666667/**668* Returns the context ClassLoader for the receiver.669*670* @return ClassLoader The context ClassLoader671*672* @see java.lang.ClassLoader673* @see #getContextClassLoader()674*/675@CallerSensitive676public ClassLoader getContextClassLoader() {677/*[PR 1FCA807]*/678/*[PR 1FDTAMT] use callerClassLoader()*/679@SuppressWarnings("removal")680SecurityManager currentManager = System.getSecurityManager();681// if there is a security manager...682if (currentManager != null) {683ClassLoader callerClassLoader = ClassLoader.callerClassLoader();684if (ClassLoader.needsClassLoaderPermissionCheck(callerClassLoader, contextClassLoader)) {685currentManager.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);686}687}688return contextClassLoader;689}690691/**692* Answers the name of the receiver.693*694* @return the receiver's name (a java.lang.String)695*/696public final String getName() {697/*[PR 1FIGT59] Return name as a String. If null, return "null" */698return String.valueOf(name);699}700701/**702* Answers the priority of the receiver.703*704* @return the receiver's priority (an <code>int</code>)705*706* @see Thread#setPriority707*/708public final int getPriority() {709return priority;710}711712/**713* Answers the ThreadGroup to which the receiver belongs714*715* @return the receiver's ThreadGroup716*/717public final ThreadGroup getThreadGroup() {718return group;719}720721722/**723* Posts an interrupt request to the receiver724*725/*[IF JAVA_SPEC_VERSION >= 14]726* From Java 14, the interrupt state for threads that are not alive is tracked.727/*[ENDIF] JAVA_SPEC_VERSION >= 14728*729* @exception SecurityException730* if <code>group.checkAccess()</code> fails with a SecurityException731*732* @see java.lang.SecurityException733* @see java.lang.SecurityManager734* @see Thread#interrupted735* @see Thread#isInterrupted736*/737public void interrupt() {738@SuppressWarnings("removal")739SecurityManager currentManager = System.getSecurityManager();740741if (currentManager != null) {742if (currentThread() != this) {743currentManager.checkAccess(this);744}745}746747synchronized (lock) {748interruptImpl();749Interruptible localBlockOn = blockOn;750if (localBlockOn != null) {751localBlockOn.interrupt(this);752}753}754}755756757/**758* Answers a <code>boolean</code> indicating whether the current Thread759* (<code>currentThread()</code>) has a pending interrupt request760* (<code>true</code>) or not (<code>false</code>). It also has the761* side-effect of clearing the flag.762*763* @return a <code>boolean</code>764*765* @see Thread#currentThread766* @see Thread#interrupt767* @see Thread#isInterrupted768*/769public static native boolean interrupted();770771/**772* Posts an interrupt request to the receiver773*774/*[IF JAVA_SPEC_VERSION >= 14]775* From Java 14, the interrupt state for threads that are not alive is tracked.776/*[ENDIF] JAVA_SPEC_VERSION >= 14777*778* @see Thread#interrupted779* @see Thread#isInterrupted780*/781private native void interruptImpl();782783/**784* Answers <code>true</code> if the receiver has785* already been started and still runs code (hasn't died yet).786* Answers <code>false</code> either if the receiver hasn't been787* started yet or if it has already started and run to completion and died.788*789* @return a <code>boolean</code>790*791* @see Thread#start792*/793public final boolean isAlive() {794synchronized (lock) {795/*[PR CMVC 88976] the Thread is alive until cleanup() is called */796return threadRef != NO_REF;797}798}799800/*[PR 1FJMO7Q] A Thread can be !isAlive() and still be in its ThreadGroup */801/**802* Answers <code>true</code> if the receiver has803* already died and been removed from the ThreadGroup804* where it belonged.805*806* @return a <code>boolean</code>807*808* @see Thread#start809* @see Thread#isAlive810*/811private boolean isDead() {812// Has already started, is not alive anymore, and has been removed from the ThreadGroup813synchronized(lock) {814return started && threadRef == NO_REF;815}816}817818/**819* Answers a <code>boolean</code> indicating whether the receiver820* is a daemon Thread (<code>true</code>) or not (<code>false</code>)821* A daemon Thread only runs as long as there are non-daemon Threads822* running. When the last non-daemon Thread ends, the whole program ends823* no matter if it had daemon Threads still running or not.824*825* @return a <code>boolean</code>826*827* @see Thread#setDaemon828*/829public final boolean isDaemon() {830return this.isDaemon;831}832833/**834* Answers a <code>boolean</code> indicating whether the receiver835* has a pending interrupt request (<code>true</code>) or not (<code>false</code>)836*837* @return a <code>boolean</code>838*839* @see Thread#interrupt840* @see Thread#interrupted841*/842public boolean isInterrupted() {843synchronized(lock) {844return isInterruptedImpl();845}846}847848private native boolean isInterruptedImpl();849850851/**852* Blocks the current Thread (<code>Thread.currentThread()</code>) until the853* receiver finishes its execution and dies.854*855* @exception InterruptedException856* if <code>interrupt()</code> was called for the receiver while857* it was in the <code>join()</code> call858*859* @see Object#notifyAll860* @see java.lang.ThreadDeath861*/862public final synchronized void join() throws InterruptedException {863if (started)864while (!isDead())865wait(0);866}867868/**869* Blocks the current Thread (<code>Thread.currentThread()</code>) until the870* receiver finishes its execution and dies or the specified timeout expires, whatever871* happens first.872*873* @param timeoutInMilliseconds The maximum time to wait (in milliseconds).874*875* @exception InterruptedException876* if <code>interrupt()</code> was called for the receiver while877* it was in the <code>join()</code> call878*879* @see Object#notifyAll880* @see java.lang.ThreadDeath881*/882public final void join(long timeoutInMilliseconds) throws InterruptedException {883join(timeoutInMilliseconds, 0);884}885886/**887* Blocks the current Thread (<code>Thread.currentThread()</code>) until the888* receiver finishes its execution and dies or the specified timeout expires, whatever889* happens first.890*891* @param timeoutInMilliseconds The maximum time to wait (in milliseconds).892* @param nanos Extra nanosecond precision893*894* @exception InterruptedException895* if <code>interrupt()</code> was called for the receiver while896* it was in the <code>join()</code> call897*898* @see Object#notifyAll899* @see java.lang.ThreadDeath900*/901public final synchronized void join(long timeoutInMilliseconds, int nanos) throws InterruptedException {902if (timeoutInMilliseconds < 0 || nanos < 0 || nanos > NANOS_MAX)903throw new IllegalArgumentException();904905if (!started || isDead()) return;906907// No nanosecond precision for now, we would need something like 'currentTimenanos'908909long totalWaited = 0;910long toWait = timeoutInMilliseconds;911boolean timedOut = false;912913/*[PR 1PQM757] Even though we do not have nano precision, we cannot wait(0) when any one of the parameters is not zero */914if (timeoutInMilliseconds == 0 & nanos > 0) {915// We either round up (1 millisecond) or down (no need to wait, just return)916if (nanos < 500000)917timedOut = true;918else919toWait = 1;920}921/*[PR 1FJMO7Q] A Thread can be !isAlive() and still be in its ThreadGroup. Use isDead() */922while (!timedOut && !isDead()) {923long start = System.currentTimeMillis();924wait(toWait);925long waited = System.currentTimeMillis() - start;926totalWaited+= waited;927toWait -= waited;928// Anyone could do a synchronized/notify on this thread, so if we wait929// less than the timeout, we must check if the thread really died930timedOut = (totalWaited >= timeoutInMilliseconds);931}932933}934935/**936* Private method that generates Thread names that comply with the Java specification937*938* @version initial939*940* @return a java.lang.String representing a name for the next Thread being generated941*942* @see Thread#createCount943*/944private synchronized static String newName() {945/*[PR 97331] Initial thread name should be Thread-0 */946if (createCount == -1) {947createCount++;948return "main"; //$NON-NLS-1$949} else {950return "Thread-" + createCount++; //$NON-NLS-1$951}952}953954/**955* This is a no-op if the receiver was never suspended, or suspended and already956* resumed. If the receiver is suspended, however, makes it resume to the point957* where it was when it was suspended.958*959* @exception SecurityException960* if <code>checkAccess()</code> fails with a SecurityException961*962* @see Thread#suspend()963*964* @deprecated Used with deprecated method Thread.suspend().965*/966/*[IF JAVA_SPEC_VERSION >= 11]*/967/*[IF JAVA_SPEC_VERSION >= 14]*/968@Deprecated(forRemoval=true, since="1.2")969/*[ELSE] JAVA_SPEC_VERSION >= 14 */970@Deprecated(forRemoval=false, since="1.2")971/*[ENDIF] JAVA_SPEC_VERSION >= 14 */972/*[ELSE] JAVA_SPEC_VERSION >= 11 */973@Deprecated974/*[ENDIF] JAVA_SPEC_VERSION >= 11 */975public final void resume() {976checkAccess();977synchronized(lock) {978resumeImpl();979}980}981982/**983* Private method for the VM to do the actual work of resuming the Thread984*985*/986private native void resumeImpl();987988/**989* Calls the <code>run()</code> method of the Runnable object the receiver holds.990* If no Runnable is set, does nothing.991*992* @see Thread#start993*/994public void run() {995if (runnable != null) {996runnable.run();997}998}9991000/**1001* Set the context ClassLoader for the receiver.1002*1003* @param cl The context ClassLoader1004*1005* @see java.lang.ClassLoader1006* @see #getContextClassLoader()1007*/1008public void setContextClassLoader(ClassLoader cl) {1009/*[PR 1FCA807]*/1010@SuppressWarnings("removal")1011SecurityManager currentManager = System.getSecurityManager();1012// if there is a security manager...1013if (currentManager != null) {1014// then check permission1015currentManager.checkPermission(com.ibm.oti.util.RuntimePermissions.permissionSetContextClassLoader);1016}1017contextClassLoader = cl;1018}10191020/**1021* Set if the receiver is a daemon Thread or not. This can only be done1022* before the Thread starts running.1023*1024* @param isDaemon A boolean indicating if the Thread should be daemon or not1025*1026* @exception SecurityException1027* if <code>checkAccess()</code> fails with a SecurityException1028*1029* @see Thread#isDaemon1030*/1031public final void setDaemon(boolean isDaemon) {1032checkAccess();1033synchronized(lock) {1034if (!this.started) {1035this.isDaemon = isDaemon;1036} else {1037/*[PR CVMC 82531] Only throw IllegalThreadStateException if the thread is alive */1038if (isAlive()) {1039throw new IllegalThreadStateException();1040}1041}1042}1043}10441045/**1046* Sets the name of the receiver.1047*1048* @param threadName new name for the Thread1049*1050* @exception SecurityException1051* if <code>checkAccess()</code> fails with a SecurityException1052*1053* @see Thread#getName1054*/1055public final void setName(String threadName) {1056checkAccess();1057/*[PR 1FIGT59]*/1058if (threadName == null) {1059throw new NullPointerException();1060}1061synchronized(lock) {1062if (started && threadRef != NO_REF) {1063setNameImpl(threadRef, threadName);1064}1065name = threadName;1066}1067}10681069private native void setNameImpl(long threadRef, String threadName);10701071/**1072* Sets the priority of the receiver. Note that the final priority set may be less than the1073* requested value, as it is bounded by the maxPriority() of the receiver's ThreadGroup.1074*1075* @param requestedPriority new priority for the Thread1076*1077* @exception SecurityException1078* if <code>checkAccess()</code> fails with a SecurityException1079* @exception IllegalArgumentException1080* if the new priority is greater than Thread.MAX_PRIORITY or less than1081* Thread.MIN_PRIORITY1082*1083* @see Thread#getPriority1084*/1085public final void setPriority(int requestedPriority){1086checkAccess();1087if (MIN_PRIORITY <= requestedPriority && requestedPriority <= MAX_PRIORITY) {1088ThreadGroup myThreadGroup = getThreadGroup();1089if (null != myThreadGroup) { /* [PR 134167 Ignore dead threads. */1090int finalPriority = requestedPriority;1091int threadGroupMaxPriority = myThreadGroup.getMaxPriority();1092if (threadGroupMaxPriority < requestedPriority) {1093finalPriority = threadGroupMaxPriority;1094}1095priority = finalPriority;1096synchronized(lock) {1097/*[PR CMVC 113440] java/lang/Thread/setPriority() Blocks GC */1098if (started && (NO_REF != threadRef)) {1099setPriorityNoVMAccessImpl(threadRef, finalPriority);1100}1101}1102}1103return;1104}1105throw new IllegalArgumentException();1106}11071108/**1109* Private method to tell the VM that the priority for the receiver is changing.1110*1111* @param priority new priority for the Thread1112*1113* @see Thread#setPriority1114*/1115private native void setPriorityNoVMAccessImpl(long threadRef, int priority);11161117/**1118* Causes the thread which sent this message to sleep an interval1119* of time (given in milliseconds). The precision is not guaranteed -1120* the Thread may sleep more or less than requested.1121*1122* @param time The time to sleep in milliseconds.1123*1124* @exception InterruptedException1125* if <code>interrupt()</code> was called for this Thread while it was sleeping1126*1127* @see Thread#interrupt()1128*/11291130public static void sleep(long time) throws InterruptedException {1131sleep(time, 0);1132}11331134/**1135* Causes the thread which sent this message to sleep an interval1136* of time (given in milliseconds). The precision is not guaranteed -1137* the Thread may sleep more or less than requested.1138*1139* @param time The time to sleep in milliseconds.1140* @param nanos Extra nanosecond precision1141*1142* @exception InterruptedException1143* if <code>interrupt()</code> was called for this Thread while it was sleeping1144*1145* @see Thread#interrupt()1146*/1147public static native void sleep(long time, int nanos) throws InterruptedException;11481149/*[IF Sidecar19-SE]*/1150/**1151* Hints to the run-time that a spin loop is being performed1152* which helps the thread in the spin loop not to use as much power.1153*1154*/1155public static native void onSpinWait();1156/*[ENDIF]*/11571158/**1159* Starts the new Thread of execution. The <code>run()</code> method of the receiver1160* will be called by the receiver Thread itself (and not the Thread calling <code>start()</code>).1161*1162* @exception IllegalThreadStateException1163* Unspecified in the Java language specification1164*1165* @see Thread#run1166*/1167public synchronized void start() {1168boolean success = false;11691170/*[PR CMVC 189553] Deadlock when a thread fails to start and another thread is ins */1171/*[IF]1172* Deadlock happens when a thread is added to the ThreadGroup1173* and its start method fails and calls its ThreadGroup's remove method for this thread to be removed while holding this thread's lock.1174* If there is another call which is holding ThreadGroup's child lock and waiting for this thread's lock,1175* then deadlock occurs since ThreadGroup's remove method is waiting for its child lock.1176*1177* Release the lock before calling threadgroup's remove method for this thread.1178/*[ENDIF]*/1179if (started) {1180/*[MSG "K0341", "Thread is already started"]*/1181throw new IllegalThreadStateException(com.ibm.oti.util.Msg.getString("K0341")); //$NON-NLS-1$1182}1183/*[PR 115667, CMVC 94448] In 1.5, thread is added to ThreadGroup when started */1184group.add(this);11851186try {1187synchronized (lock) {1188startImpl();1189success = true;1190}1191} finally {1192if (!success) {1193group.remove(this);1194}1195}1196}11971198private native void startImpl();11991200/**1201* Requests the receiver Thread to stop and throw ThreadDeath.1202* The Thread is resumed if it was suspended and awakened if it was1203* sleeping, so that it can proceed to throw ThreadDeath.1204*1205* @exception SecurityException1206* if <code>checkAccess()</code> fails with a SecurityException1207*1208* @deprecated1209*/1210/*[IF JAVA_SPEC_VERSION >= 18]*/1211@Deprecated(forRemoval=true, since="1.2")1212/*[ELSEIF JAVA_SPEC_VERSION >= 9]*/1213@Deprecated(forRemoval=false, since="1.2")1214/*[ELSE]*/1215@Deprecated1216/*[ENDIF]*/1217public final void stop() {1218/*[PR CMVC 94728] AccessControlException on dead Thread */1219/* the only case we don't want to do the check is if the thread has been started but is now dead */1220if (!isDead()){1221stopWithThrowable(new ThreadDeath());1222}1223}12241225/*[IF JAVA_SPEC_VERSION < 11]*/1226/**1227* Throws UnsupportedOperationException.1228*1229* @param throwable Throwable object to be thrown by the Thread1230*1231* @deprecated1232*/1233/*[IF Sidecar19-SE]*/1234@Deprecated(forRemoval=true, since="1.2")1235/*[ELSE]*/1236@Deprecated1237/*[ENDIF]*/1238public final void stop(Throwable throwable) {1239throw new UnsupportedOperationException();1240}1241/*[ENDIF] JAVA_SPEC_VERSION < 11 */12421243private final synchronized void stopWithThrowable(Throwable throwable) {1244checkAccess();1245/*[PR 95390]*/1246if ((currentThread() != this) || !(throwable instanceof ThreadDeath)) {1247@SuppressWarnings("removal")1248SecurityManager currentManager = System.getSecurityManager();1249if (currentManager != null) {1250currentManager.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);1251}1252}12531254synchronized (lock) {1255if (throwable != null) {1256if (!started) {1257/* [PR CMVC 179978] Java7:JCK:java_lang.Thread fails in all plat*/1258/*1259* if the thread has not yet been simply store the fact that stop has been called1260* The JVM uses this to determine if stop has been called before start1261*/1262stopCalled = true;1263} else {1264/* thread was started so do the full stop */1265stopImpl(throwable);1266}1267} else {1268throw new NullPointerException();1269}1270}1271}12721273/**1274* Private method for the VM to do the actual work of stopping the Thread1275*1276* @param throwable Throwable object to be thrown by the Thread1277*/1278private native void stopImpl(Throwable throwable);12791280/**1281* This is a no-op if the receiver is suspended. If the receiver <code>isAlive()</code>1282* however, suspended it until <code>resume()</code> is sent to it. Suspend requests1283* are not queued, which means that N requests are equivalent to just one - only one1284* resume request is needed in this case.1285*1286* @exception SecurityException1287* if <code>checkAccess()</code> fails with a SecurityException1288*1289* @see Thread#resume()1290*1291* @deprecated May cause deadlocks.1292*/1293/*[IF JAVA_SPEC_VERSION >= 11]*/1294/*[IF JAVA_SPEC_VERSION >= 14]*/1295@Deprecated(forRemoval=true, since="1.2")1296/*[ELSE] JAVA_SPEC_VERSION >= 14 */1297@Deprecated(forRemoval=false, since="1.2")1298/*[ENDIF] JAVA_SPEC_VERSION >= 14 */1299/*[ELSE] JAVA_SPEC_VERSION >= 11 */1300@Deprecated1301/*[ENDIF] JAVA_SPEC_VERSION >= 11 */1302public final void suspend() {1303checkAccess();1304/*[PR 106321]*/1305if (currentThread() == this) {1306suspendImpl();1307} else {1308synchronized (lock) {1309suspendImpl();1310}1311}1312}13131314/**1315* Private method for the VM to do the actual work of suspending the Thread1316*1317* Conceptually this method can't be synchronized or a Thread that suspends itself will1318* do so with the Thread's lock and this will cause deadlock to valid Java programs.1319*/1320private native void suspendImpl();13211322/*[PR 97801]*/1323/**1324* Answers a string containing a concise, human-readable1325* description of the receiver.1326*1327* @return a printable representation for the receiver.1328*/1329public String toString() {1330/*[PR JAZZ 85499] : NullPointerException from Thread.toString() */1331ThreadGroup localGroup = getThreadGroup();13321333return "Thread[" + this.getName() + "," + this.getPriority() + "," + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$1334/*[PR 97317] Handle a null thread group */1335(null == localGroup ? "" : localGroup.getName()) + "]" ; //$NON-NLS-1$ //$NON-NLS-2$1336}13371338/**1339* Causes the thread which sent this message to yield execution to another Thread1340* that is ready to run. The actual scheduling is implementation-dependent.1341*1342* @version initial1343*/1344public static native void yield();13451346/**1347* Returns whether the current thread has a monitor lock on the specified object.1348*1349* @param object the object to test for the monitor lock1350* @return true when the current thread has a monitor lock on the specified object1351*1352* @since 1.41353*/1354public static native boolean holdsLock(Object object);13551356/*[IF JAVA_SPEC_VERSION >= 11]*/1357static1358/*[ENDIF] JAVA_SPEC_VERSION >= 11 */1359void blockedOn(Interruptible interruptible) {1360Thread currentThread;1361/*[IF JAVA_SPEC_VERSION >= 11]*/1362currentThread = currentThread();1363/*[ELSE] JAVA_SPEC_VERSION >= 111364currentThread = this;1365/*[ENDIF] JAVA_SPEC_VERSION >= 11 */1366synchronized (currentThread.lock) {1367currentThread.blockOn = interruptible;1368}1369}137013711372private native Throwable getStackTraceImpl();13731374/**1375* Returns an array of StackTraceElement, where each element of the array represents a frame1376* on the Java stack.1377*1378* @return an array of StackTraceElement1379*1380* @throws SecurityException if the RuntimePermission "getStackTrace" is not allowed1381*1382* @see java.lang.StackTraceElement1383*/1384public StackTraceElement[] getStackTrace() {1385if (Thread.currentThread() != this) {1386@SuppressWarnings("removal")1387SecurityManager security = System.getSecurityManager();1388if (security != null) {1389security.checkPermission(SecurityConstants.GET_STACK_TRACE_PERMISSION); //$NON-NLS-1$1390}1391}1392Throwable t;13931394synchronized (lock) {1395if (!isAlive()) {1396return EMPTY_STACK_TRACE;1397}1398t = getStackTraceImpl();1399}1400return J9VMInternals.getStackTrace(t, false);1401}14021403/**1404* Returns a Map containing Thread keys, and values which are arrays of StackTraceElement. The Map contains1405* all Threads which were alive at the time this method was called.1406*1407* @return an array of StackTraceElement1408*1409* @throws SecurityException if the RuntimePermission "getStackTrace" is not allowed, or the1410* RuntimePermission "modifyThreadGroup" is not allowed1411*1412* @see #getStackTrace()1413*/1414public static Map<Thread, StackTraceElement[]> getAllStackTraces() {1415@SuppressWarnings("removal")1416SecurityManager security = System.getSecurityManager();1417if (security != null) {1418security.checkPermission(SecurityConstants.GET_STACK_TRACE_PERMISSION);1419security.checkPermission(SecurityConstants.MODIFY_THREADGROUP_PERMISSION);1420}1421// Allow room for more Threads to be created before calling enumerate()1422int count = systemThreadGroup.activeCount() + 20;1423Thread[] threads = new Thread[count];1424count = systemThreadGroup.enumerate(threads);1425Map<Thread, StackTraceElement[]> result = new java.util.HashMap<>(count);1426for (int i = 0; i < count; i++) {1427result.put(threads[i], threads[i].getStackTrace());1428}1429return result;1430}14311432/**1433* Return a unique id for this Thread.1434*1435* @return a positive unique id for this Thread.1436*/1437public long getId() {1438return tid;1439}14401441/**1442* A handler which is invoked when an uncaught exception occurs in a Thread.1443*/1444@FunctionalInterface1445public static interface UncaughtExceptionHandler {1446/**1447* The method invoked when an uncaught exception occurs in a Thread.1448*1449* @param thread the Thread where the uncaught exception occurred1450* @param throwable the uncaught exception1451*/1452public void uncaughtException(Thread thread, Throwable throwable) ;1453}14541455/**1456* Return the UncaughtExceptionHandler for this Thread.1457*1458* @return the UncaughtExceptionHandler for this Thread1459*1460* @see UncaughtExceptionHandler1461*/1462public UncaughtExceptionHandler getUncaughtExceptionHandler() {1463if (exceptionHandler == null)1464return getThreadGroup();1465return exceptionHandler;1466}14671468/**1469* Set the UncaughtExceptionHandler for this Thread.1470*1471* @param handler the UncaughtExceptionHandler to set1472*1473* @see UncaughtExceptionHandler1474*/1475public void setUncaughtExceptionHandler(UncaughtExceptionHandler handler) {1476exceptionHandler = handler;1477}14781479/**1480* Return the default UncaughtExceptionHandler used for new Threads.1481*1482* @return the default UncaughtExceptionHandler for new Threads1483*1484* @see UncaughtExceptionHandler1485*/1486public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() {1487return defaultExceptionHandler;1488}14891490/**1491* Set the UncaughtExceptionHandler used for new Threads.1492*1493* @param handler the UncaughtExceptionHandler to set1494*1495* @see UncaughtExceptionHandler1496*/1497public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler handler) {1498SecurityManager security = System.getSecurityManager();1499if (security != null)1500security.checkPermission(com.ibm.oti.util.RuntimePermissions.permissionSetDefaultUncaughtExceptionHandler);1501defaultExceptionHandler = handler;1502}15031504/**1505* The possible Thread states.1506*/1507// The order of the States is known by the getStateImpl() native1508public static enum State {1509/**1510* A Thread which has not yet started.1511*/1512NEW,1513/**1514* A Thread which is running or suspended.1515*/1516RUNNABLE,1517/**1518* A Thread which is blocked on a monitor.1519*/1520BLOCKED,1521/**1522* A Thread which is waiting with no timeout.1523*/1524WAITING,1525/**1526* A Thread which is waiting with a timeout.1527*/1528TIMED_WAITING,1529/**1530* A thread which is no longer alive.1531*/1532TERMINATED }15331534/**1535* Returns the current Thread state.1536*1537* @return the current Thread state constant.1538*1539* @see State1540*/1541public State getState() {1542synchronized(lock) {1543if (threadRef == NO_REF) {1544if (isDead()) {1545return State.TERMINATED;1546}1547return State.NEW;1548}1549return State.values()[getStateImpl(threadRef)];1550}1551}15521553private native int getStateImpl(long threadRef);15541555/**1556* Any uncaught exception in any Thread has to be forwarded (by the VM) to the Thread's ThreadGroup1557* by sending this message (uncaughtException). This allows users to define custom ThreadGroup classes1558* and custom behavior for when a Thread has an uncaughtException or when it does (ThreadDeath).1559*1560* @version initial1561*1562* @param e The uncaught exception itself1563*1564* @see Thread#stop()1565* @see Thread#stop(Throwable)1566* @see ThreadDeath1567*/1568void uncaughtException(Throwable e) {1569UncaughtExceptionHandler handler = getUncaughtExceptionHandler();1570if (handler != null)1571handler.uncaughtException(this, e);1572}15731574/**1575* Called by J9VMInternals.threadCleanup() so the Thread can release resources1576* and change its state.1577*1578* @see J9VMInternals#threadCleanup()1579*/1580void cleanup() {1581/*[IF JAVA_SPEC_VERSION >= 14]*/1582/* Refresh deadInterrupt value so it is accurate when thread reference is removed. */1583deadInterrupt = interrupted();1584/*[ENDIF] JAVA_SPEC_VERSION >= 14 */15851586/*[IF Sidecar18-SE-OpenJ9]*/1587if ((threadLocals != null) && TerminatingThreadLocal.REGISTRY.isPresent()) {1588TerminatingThreadLocal.threadTerminated();1589}1590/*[ENDIF] Sidecar18-SE-OpenJ9 */15911592/*[PR 97317]*/1593group = null;15941595/*[PR CVMC 118827] references are not removed in dead threads */1596runnable = null;1597inheritedAccessControlContext = null;15981599threadLocals = null;1600inheritableThreadLocals = null;16011602synchronized(lock) {1603threadRef = Thread.NO_REF; // So that isAlive() can work1604}1605}16061607// prevent subclasses from becoming Cloneable1608protected Object clone() throws CloneNotSupportedException {1609throw new CloneNotSupportedException();1610}16111612}161316141615