Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/jcl/src/java.base/share/classes/java/lang/Thread.java
12513 views
1
/*[INCLUDE-IF Sidecar18-SE & !OPENJDK_THREAD_SUPPORT]*/
2
/*******************************************************************************
3
* Copyright (c) 1998, 2022 IBM Corp. and others
4
*
5
* This program and the accompanying materials are made available under
6
* the terms of the Eclipse Public License 2.0 which accompanies this
7
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
8
* or the Apache License, Version 2.0 which accompanies this distribution and
9
* is available at https://www.apache.org/licenses/LICENSE-2.0.
10
*
11
* This Source Code may also be made available under the following
12
* Secondary Licenses when the conditions for such availability set
13
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
14
* General Public License, version 2 with the GNU Classpath
15
* Exception [1] and GNU General Public License, version 2 with the
16
* OpenJDK Assembly Exception [2].
17
*
18
* [1] https://www.gnu.org/software/classpath/license.html
19
* [2] http://openjdk.java.net/legal/assembly-exception.html
20
*
21
* 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-exception
22
*******************************************************************************/
23
package java.lang;
24
25
import java.util.Map;
26
import java.security.AccessControlContext;
27
import java.security.AccessController;
28
import java.security.PrivilegedAction;
29
/*[IF Sidecar18-SE-OpenJ9]*/
30
import jdk.internal.misc.TerminatingThreadLocal;
31
/*[ENDIF] Sidecar18-SE-OpenJ9 */
32
import sun.security.util.SecurityConstants;
33
/*[IF JAVA_SPEC_VERSION >= 11]*/
34
import java.io.FileDescriptor;
35
import java.nio.charset.Charset;
36
import java.util.Properties;
37
import jdk.internal.reflect.CallerSensitive;
38
/*[ELSE] JAVA_SPEC_VERSION >= 11 */
39
import sun.reflect.CallerSensitive;
40
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
41
import java.lang.reflect.Method;
42
import sun.nio.ch.Interruptible;
43
44
/**
45
* A Thread is a unit of concurrent execution in Java. It has its own call stack
46
* for methods being called and their parameters. Threads in the same VM interact and
47
* synchronize by the use of shared Objects and monitors associated with these objects.
48
* Synchronized methods and part of the API in Object also allow Threads to cooperate.
49
*
50
* When a Java program starts executing there is an implicit Thread (called "main")
51
* which is automatically created by the VM. This Thread belongs to a ThreadGroup
52
* (also called "main") which is automatically created by the bootstrap sequence by
53
* the VM as well.
54
*
55
* @see java.lang.Object
56
* @see java.lang.ThreadGroup
57
*/
58
public class Thread implements Runnable {
59
60
/* Maintain thread shape in all configs */
61
62
/**
63
* The maximum priority value for a Thread.
64
*/
65
public final static int MAX_PRIORITY = 10; // Maximum allowed priority for a thread
66
/**
67
* The minimum priority value for a Thread.
68
*/
69
public final static int MIN_PRIORITY = 1; // Minimum allowed priority for a thread
70
/**
71
* The default priority value for a Thread.
72
*/
73
public final static int NORM_PRIORITY = 5; // Normal priority for a thread
74
/*[PR 97331] Initial thread name should be Thread-0 */
75
private static int createCount = -1; // Used internally to compute Thread names that comply with the Java specification
76
/*[PR 122459] LIR646 - Remove use of generic object for synchronization */
77
private static final class TidLock {
78
TidLock() {}
79
}
80
private static Object tidLock = new TidLock();
81
private static long tidCount = 1;
82
private static final int NANOS_MAX = 999999; // Max value for nanoseconds parameter to sleep and join
83
private static final int INITIAL_LOCAL_STORAGE_CAPACITY = 5; // Initial number of local storages when the Thread is created
84
static final long NO_REF = 0; // Symbolic constant, no threadRef assigned or already cleaned up
85
86
// Instance variables
87
private long threadRef; // Used by the VM
88
long stackSize = 0;
89
/*[IF JAVA_SPEC_VERSION >= 14]*/
90
/* deadInterrupt tracks the thread interrupt state when threadRef has no reference (ie thread is not alive).
91
* Note that this value need not be updated while the thread is running since the interrupt state will be
92
* tracked by the vm during that time. Because of this the value should not be used over calling
93
* isInterrupted() or interrupted().
94
*/
95
private volatile boolean deadInterrupt;
96
/*[ENDIF] JAVA_SPEC_VERSION >= 14 */
97
private volatile boolean started; // If !isAlive(), tells if Thread died already or hasn't even started
98
private String name; // The Thread's name
99
private int priority = NORM_PRIORITY; // The Thread's current priority
100
private boolean isDaemon; // Tells if the Thread is a daemon thread or not.
101
102
ThreadGroup group; // A Thread belongs to exactly one ThreadGroup
103
private Runnable runnable; // Target (optional) runnable object
104
private boolean stopCalled = false; // Used by the VM
105
/*[PR 1FENTZW]*/
106
private ClassLoader contextClassLoader; // Used to find classes and resources in this Thread
107
ThreadLocal.ThreadLocalMap threadLocals;
108
private java.security.AccessControlContext inheritedAccessControlContext;
109
110
/*[PR 96127]*/
111
/*[PR 122459] LIR646 - Remove use of generic object for synchronization */
112
private static final class ThreadLock {}
113
private Object lock = new ThreadLock();
114
115
ThreadLocal.ThreadLocalMap inheritableThreadLocals;
116
private volatile Interruptible blockOn;
117
118
int threadLocalsIndex;
119
int inheritableThreadLocalsIndex;
120
121
/*[PR 113602] Thread fields should be volatile */
122
private volatile UncaughtExceptionHandler exceptionHandler;
123
private long tid;
124
125
volatile Object parkBlocker;
126
127
private static ThreadGroup systemThreadGroup; // Assigned by the vm
128
private static ThreadGroup mainGroup; // ThreadGroup where the "main" Thread starts
129
130
/*[PR 113602] Thread fields should be volatile */
131
private volatile static UncaughtExceptionHandler defaultExceptionHandler;
132
133
/*[PR CMVC 196696] Build error:java.lang.Thread need extra fields */
134
long threadLocalRandomSeed;
135
int threadLocalRandomProbe;
136
int threadLocalRandomSecondarySeed;
137
138
private static final StackTraceElement[] EMPTY_STACK_TRACE = new StackTraceElement[0];
139
140
/**
141
* Constructs a new Thread with no runnable object and a newly generated name.
142
* The new Thread will belong to the same ThreadGroup as the Thread calling
143
* this constructor.
144
*
145
* @see java.lang.ThreadGroup
146
*/
147
public Thread() {
148
this(null, null, newName(), null, true);
149
}
150
151
/**
152
*
153
* Private constructor to be used by the VM for the threads attached through JNI.
154
* They already have a running thread with no associated Java Thread, so this is
155
* where the binding is done.
156
*
157
* @param vmName Name for the Thread being created (or null to auto-generate a name)
158
* @param vmThreadGroup ThreadGroup for the Thread being created (or null for main threadGroup)
159
* @param vmPriority Priority for the Thread being created
160
* @param vmIsDaemon Indicates whether or not the Thread being created is a daemon thread
161
*
162
* @see java.lang.ThreadGroup
163
*/
164
private Thread(String vmName, Object vmThreadGroup, int vmPriority, boolean vmIsDaemon) {
165
super();
166
167
String threadName = (vmName == null) ? newName() : vmName;
168
/*[IF JAVA_SPEC_VERSION < 15]*/
169
setNameImpl(threadRef, threadName);
170
/*[ENDIF] JAVA_SPEC_VERSION < 15 */
171
name = threadName;
172
173
isDaemon = vmIsDaemon;
174
priority = vmPriority; // If we called setPriority(), it would have to be after setting the ThreadGroup (further down),
175
// because of the checkAccess() call (which requires the ThreadGroup set). However, for the main
176
// Thread or JNI-C attached Threads we just trust the value the VM is passing us, and just assign.
177
178
ThreadGroup threadGroup = null;
179
boolean booting = false;
180
if (mainGroup == null) { // only occurs during bootstrap
181
booting = true;
182
/*[PR CMVC 71192] Initialize the "main" thread group without calling checkAccess() */
183
mainGroup = new ThreadGroup(systemThreadGroup);
184
} else {
185
/*[IF JAVA_SPEC_VERSION >= 15]*/
186
setNameImpl(threadRef, threadName);
187
/*[ENDIF] JAVA_SPEC_VERSION >= 15 */
188
}
189
threadGroup = vmThreadGroup == null ? mainGroup : (ThreadGroup)vmThreadGroup;
190
191
/*[PR 1FEVFSU] The rest of the configuration/initialization is shared between this constructor and the public one */
192
initialize(booting, threadGroup, null, null, true); // no parent Thread
193
/*[PR 115667, CMVC 94448] In 1.5 and CDC/Foundation 1.1, thread is added to ThreadGroup when started */
194
this.group.add(this);
195
196
/*[PR 100718] Initialize System.in after the main thread */
197
if (booting) {
198
/*[IF JAVA_SPEC_VERSION >= 15]*/
199
/* JDK15+ native method binding uses java.lang.ClassLoader.findNative():bootstrapClassLoader.nativelibs.find(entryName)
200
* to lookup native address when not found within systemClassLoader native libraries.
201
* This requires bootstrapClassLoader is initialized via initialize(booting, threadGroup, null, null, true) above before
202
* invoking a native method not present within systemClassLoader native libraries such as following setNameImpl modified
203
* via JVMTI agent SetNativeMethodPrefix (https://github.com/eclipse-openj9/openj9/issues/11181).
204
* After bootstrapClassLoader initialization, setNameImpl can be invoked before initialize() to set thread name earlier.
205
*/
206
setNameImpl(threadRef, threadName);
207
/*[ENDIF] JAVA_SPEC_VERSION >= 15 */
208
System.completeInitialization();
209
}
210
}
211
212
/*
213
* Called after everything else is initialized.
214
*/
215
void completeInitialization() {
216
// Get the java.system.class.loader
217
/*[PR CMVC 99755] Implement -Djava.system.class.loader option */
218
contextClassLoader = ClassLoader.getSystemClassLoader();
219
/*[IF Sidecar19-SE]*/
220
jdk.internal.misc.VM.initLevel(4);
221
/*[ELSE]*/ // Sidecar19-SE
222
sun.misc.VM.booted();
223
/*[ENDIF]*/ // Sidecar19-SE
224
/*[IF Sidecar19-SE|Sidecar18-SE-OpenJ9]*/
225
System.startSNMPAgent();
226
/*[ENDIF]*/ // Sidecar19-SE|Sidecar18-SE-OpenJ9
227
228
/*[IF JAVA_SPEC_VERSION >= 11] */
229
/* Although file.encoding is used to set the default Charset, some Charset's are not available
230
* in the java.base module and so are not used at startup. There are additional Charset's in the
231
* jdk.charsets module, which is only loaded later. This means the default Charset may not be the
232
* same as file.encoding. Now that all modules and Charset's are available, check if the desired
233
* encodings can be used for System.err and System.out.
234
*/
235
Properties props = System.internalGetProperties();
236
// If the sun.stderr.encoding was already set in System, don't change the encoding
237
if (!System.hasSetErrEncoding()) {
238
Charset stderrCharset = System.getCharset(props.getProperty("sun.stderr.encoding"), true); //$NON-NLS-1$
239
if (stderrCharset != null) {
240
System.err.flush();
241
System.setErr(System.createConsole(FileDescriptor.err, stderrCharset));
242
}
243
}
244
245
// If the sun.stdout.encoding was already set in System, don't change the encoding
246
if (!System.hasSetOutEncoding()) {
247
Charset stdoutCharset = System.getCharset(props.getProperty("sun.stdout.encoding"), true); //$NON-NLS-1$
248
if (stdoutCharset != null) {
249
System.out.flush();
250
System.setOut(System.createConsole(FileDescriptor.out, stdoutCharset));
251
}
252
}
253
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
254
}
255
256
/**
257
* Constructs a new Thread with a runnable object and a newly generated name.
258
* The new Thread will belong to the same ThreadGroup as the Thread calling
259
* this constructor.
260
*
261
* @param runnable a java.lang.Runnable whose method <code>run</code> will be executed by the new Thread
262
*
263
* @see java.lang.ThreadGroup
264
* @see java.lang.Runnable
265
*/
266
public Thread(Runnable runnable) {
267
this(null, runnable, newName(), null, true);
268
}
269
270
/*
271
* [PR CMVC 199693] Prevent a trusted method chain attack.
272
*/
273
274
/**
275
* Constructs a new Thread with a runnable object and a newly generated name,
276
* setting the specified AccessControlContext.
277
* The new Thread will belong to the same ThreadGroup as the Thread calling
278
* this constructor.
279
*
280
* @param runnable a java.lang.Runnable whose method <code>run</code> will be executed by the new Thread
281
* @param acc the AccessControlContext to use for the Thread
282
*
283
* @see java.lang.ThreadGroup
284
* @see java.lang.Runnable
285
*/
286
Thread(Runnable runnable, AccessControlContext acc) {
287
this(null, runnable, newName(), acc, true);
288
}
289
290
/**
291
* Constructs a new Thread with a runnable object and name provided.
292
* The new Thread will belong to the same ThreadGroup as the Thread calling
293
* this constructor.
294
*
295
* @param runnable a java.lang.Runnable whose method <code>run</code> will be executed by the new Thread
296
* @param threadName Name for the Thread being created
297
*
298
* @see java.lang.ThreadGroup
299
* @see java.lang.Runnable
300
*/
301
public Thread(Runnable runnable, String threadName) {
302
this(null, runnable, threadName, null, true);
303
}
304
305
306
/**
307
* Constructs a new Thread with no runnable object and the name provided.
308
* The new Thread will belong to the same ThreadGroup as the Thread calling
309
* this constructor.
310
*
311
* @param threadName Name for the Thread being created
312
*
313
* @see java.lang.ThreadGroup
314
* @see java.lang.Runnable
315
*/
316
public Thread(String threadName) {
317
this(null, null, threadName, null, true);
318
}
319
320
/**
321
* Constructs a new Thread with a runnable object and a newly generated name.
322
* The new Thread will belong to the ThreadGroup passed as parameter.
323
*
324
* @param group ThreadGroup to which the new Thread will belong
325
* @param runnable a java.lang.Runnable whose method <code>run</code> will be executed by the new Thread
326
*
327
* @exception SecurityException
328
* if <code>group.checkAccess()</code> fails with a SecurityException
329
* @exception IllegalThreadStateException
330
* if <code>group.destroy()</code> has already been done
331
*
332
* @see java.lang.ThreadGroup
333
* @see java.lang.Runnable
334
* @see java.lang.SecurityException
335
* @see java.lang.SecurityManager
336
*/
337
public Thread(ThreadGroup group, Runnable runnable) {
338
this(group, runnable, newName(), null, true);
339
}
340
341
/**
342
* Constructs a new Thread with a runnable object, the given name and
343
* belonging to the ThreadGroup passed as parameter.
344
*
345
* @param group ThreadGroup to which the new Thread will belong
346
* @param runnable a java.lang.Runnable whose method <code>run</code> will be executed by the new Thread
347
* @param threadName Name for the Thread being created
348
* @param stack Platform dependent stack size
349
*
350
* @exception SecurityException
351
* if <code>group.checkAccess()</code> fails with a SecurityException
352
* @exception IllegalThreadStateException
353
* if <code>group.destroy()</code> has already been done
354
*
355
* @since 1.4
356
*
357
* @see java.lang.ThreadGroup
358
* @see java.lang.Runnable
359
* @see java.lang.SecurityException
360
* @see java.lang.SecurityManager
361
*/
362
public Thread(ThreadGroup group, Runnable runnable, String threadName, long stack) {
363
this(group, runnable, threadName, null, true);
364
this.stackSize = stack;
365
}
366
367
/*[IF Sidecar19-SE]*/
368
/**
369
* Constructs a new Thread with a runnable object, the given name, the thread stack size,
370
* the flag to inherit initial values for inheritable thread-local variables and
371
* belonging to the ThreadGroup passed as parameter.
372
*
373
* @param group ThreadGroup to which the new Thread will belong
374
* @param runnable A java.lang.Runnable whose method <code>run</code> will be executed by the new Thread
375
* @param threadName Name for the Thread being created
376
* @param stack Platform dependent stack size
377
* @param inheritThreadLocals A boolean indicating whether to inherit initial values for inheritable thread-local variables.
378
*
379
* @exception SecurityException
380
* if <code>group.checkAccess()</code> fails with a SecurityException
381
* @exception IllegalThreadStateException
382
* if <code>group.destroy()</code> has already been done
383
*
384
*/
385
public Thread(ThreadGroup group, Runnable runnable, String threadName, long stack, boolean inheritThreadLocals) {
386
this(group, runnable, threadName, null, inheritThreadLocals);
387
this.stackSize = stack;
388
}
389
/*[ENDIF]*/
390
391
/**
392
* Constructs a new Thread with a runnable object, the given name and
393
* belonging to the ThreadGroup passed as parameter.
394
*
395
* @param group ThreadGroup to which the new Thread will belong
396
* @param runnable a java.lang.Runnable whose method <code>run</code> will be executed by the new Thread
397
* @param threadName Name for the Thread being created
398
*
399
* @exception SecurityException
400
* if <code>group.checkAccess()</code> fails with a SecurityException
401
* @exception IllegalThreadStateException
402
* if <code>group.destroy()</code> has already been done
403
*
404
* @see java.lang.ThreadGroup
405
* @see java.lang.Runnable
406
* @see java.lang.SecurityException
407
* @see java.lang.SecurityManager
408
*/
409
public Thread(ThreadGroup group, Runnable runnable, String threadName) {
410
this(group, runnable, threadName, null, true);
411
}
412
413
Thread(Runnable runnable, String threadName, boolean isSystemThreadGroup, boolean inheritThreadLocals, boolean isDaemon, ClassLoader contextClassLoader) {
414
this(isSystemThreadGroup ? systemThreadGroup : null, runnable, threadName, null, inheritThreadLocals);
415
this.isDaemon = isDaemon;
416
this.contextClassLoader = contextClassLoader;
417
}
418
419
private Thread(ThreadGroup group, Runnable runnable, String threadName, AccessControlContext acc, boolean inheritThreadLocals) {
420
super();
421
/*[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 */
422
/*[PR 1FIGT59] name cannot be null*/
423
if (threadName==null) throw new NullPointerException();
424
this.name = threadName; // We avoid the public API 'setName', since it does redundant work (checkAccess)
425
this.runnable = runnable; // No API available here, so just direct access to inst. var.
426
Thread currentThread = currentThread();
427
428
this.isDaemon = currentThread.isDaemon(); // We avoid the public API 'setDaemon', since it does redundant work (checkAccess)
429
430
/*[PR 1FEO92F] (dup of 1FC0TRN) */
431
if (group == null) {
432
@SuppressWarnings("removal")
433
SecurityManager currentManager = System.getSecurityManager();
434
// if there is a security manager...
435
if (currentManager != null)
436
// Ask SecurityManager for ThreadGroup
437
group = currentManager.getThreadGroup();
438
}
439
/*[PR 94235]*/
440
if (group == null)
441
// Same group as Thread that created us
442
group = currentThread.getThreadGroup();
443
444
445
/*[PR 1FEVFSU] The rest of the configuration/initialization is shared between this constructor and the private one */
446
initialize(false, group, currentThread, acc, inheritThreadLocals);
447
448
setPriority(currentThread.getPriority()); // In this case we can call the public API according to the spec - 20.20.10
449
}
450
451
/**
452
* Initialize the thread according to its parent Thread and the ThreadGroup
453
* where it should be added.
454
*
455
* @param booting Indicates if the JVM is booting up, i.e. if the main thread is being attached
456
* @param threadGroup ThreadGroup The ThreadGroup to which the receiver is being added.
457
* @param parentThread Thread The creator Thread from which to inherit some values like local storage, etc.
458
* If null, the receiver is either the main Thread or a JNI-C attached Thread.
459
* @param acc The AccessControlContext. If null, use the current context
460
* @param inheritThreadLocals A boolean indicating whether to inherit initial values for inheritable thread-local variables.
461
*/
462
private void initialize(boolean booting, ThreadGroup threadGroup, Thread parentThread, AccessControlContext acc, boolean inheritThreadLocals) {
463
synchronized (tidLock) {
464
tid = tidCount++;
465
}
466
467
/*[PR 96408]*/
468
this.group = threadGroup;
469
470
471
if (booting) {
472
System.afterClinitInitialization();
473
}
474
475
476
// initialize the thread local storage before making other calls
477
if (parentThread != null) { // Non-main thread
478
if (inheritThreadLocals && (null != parentThread.inheritableThreadLocals)) {
479
inheritableThreadLocals = ThreadLocal.createInheritedMap(parentThread.inheritableThreadLocals);
480
}
481
482
/*[PR CMVC 90230] enableContextClassLoaderOverride check added in 1.5 */
483
@SuppressWarnings("removal")
484
final SecurityManager sm = System.getSecurityManager();
485
final Class<?> implClass = getClass();
486
final Class<?> thisClass = Thread.class;
487
if ((sm != null) && (implClass != thisClass)) {
488
boolean override = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
489
@Override
490
public Boolean run() {
491
try {
492
Method method = implClass.getMethod("getContextClassLoader"); //$NON-NLS-1$
493
if (method.getDeclaringClass() != thisClass) {
494
return Boolean.TRUE;
495
}
496
} catch (NoSuchMethodException e) {
497
}
498
try {
499
Method method = implClass.getDeclaredMethod("setContextClassLoader", ClassLoader.class); //$NON-NLS-1$
500
if (method.getDeclaringClass() != thisClass) {
501
return Boolean.TRUE;
502
}
503
} catch (NoSuchMethodException e) {
504
}
505
return Boolean.FALSE;
506
}
507
}).booleanValue();
508
if (override) {
509
sm.checkPermission(com.ibm.oti.util.RuntimePermissions.permissionEnableContextClassLoaderOverride);
510
}
511
}
512
// By default a Thread "inherits" the context ClassLoader from its creator
513
/*[PR CMVC 90230] behavior change in 1.5, call getContextClassLoader() instead of accessing field */
514
contextClassLoader = parentThread.getContextClassLoader();
515
} else { // no parent: main thread, or one attached through JNI-C
516
/*[PR 111189] Do not initialize ClassLoaders in a static initializer */
517
if (booting) {
518
// Preload and initialize the JITHelpers class
519
try {
520
Class.forName("com.ibm.jit.JITHelpers"); //$NON-NLS-1$
521
} catch(ClassNotFoundException e) {
522
// Continue silently if the class can't be loaded and initialized for some reason,
523
// The JIT will tolerate this.
524
}
525
526
// Explicitly initialize ClassLoaders, so ClassLoader methods (such as
527
// ClassLoader.callerClassLoader) can be used before System is initialized
528
ClassLoader.initializeClassLoaders();
529
}
530
// Just set the context class loader
531
contextClassLoader = ClassLoader.getSystemClassLoader();
532
}
533
534
threadGroup.checkAccess();
535
/*[PR 115667, CMVC 94448] In 1.5 and CDC/Foundation 1.1, thread is added to ThreadGroup when started */
536
threadGroup.checkNewThread(this);
537
538
inheritedAccessControlContext = acc == null ? AccessController.getContext() : acc;
539
}
540
541
/**
542
* Constructs a new Thread with no runnable object, the given name and
543
* belonging to the ThreadGroup passed as parameter.
544
*
545
* @param group ThreadGroup to which the new Thread will belong
546
* @param threadName Name for the Thread being created
547
*
548
* @exception SecurityException
549
* if <code>group.checkAccess()</code> fails with a SecurityException
550
* @exception IllegalThreadStateException
551
* if <code>group.destroy()</code> has already been done
552
*
553
* @see java.lang.ThreadGroup
554
* @see java.lang.SecurityException
555
* @see java.lang.SecurityManager
556
*/
557
public Thread(ThreadGroup group, String threadName) {
558
this(group, null, threadName, null, true);
559
}
560
561
/**
562
* Returns how many threads are active in the <code>ThreadGroup</code>
563
* which the current thread belongs to.
564
*
565
* @return Number of Threads
566
*/
567
public static int activeCount(){
568
/*[PR CMVC 93001] changed in 1.5 to only count active threads */
569
return currentThread().getThreadGroup().activeCount();
570
}
571
572
573
/**
574
* This method is used for operations that require approval from
575
* a SecurityManager. If there's none installed, this method is a no-op.
576
* If there's a SecurityManager installed , <code>checkAccess(Ljava.lang.Thread;)</code>
577
* is called for that SecurityManager.
578
*
579
* @see java.lang.SecurityException
580
* @see java.lang.SecurityManager
581
*/
582
/*[IF JAVA_SPEC_VERSION >= 17]*/
583
@Deprecated(since="17", forRemoval=true)
584
/*[ENDIF] JAVA_SPEC_VERSION >= 17 */
585
public final void checkAccess() {
586
@SuppressWarnings("removal")
587
SecurityManager currentManager = System.getSecurityManager();
588
if (currentManager != null) currentManager.checkAccess(this);
589
}
590
591
/**
592
* Returns the number of stack frames in this thread.
593
*
594
* @return Number of stack frames
595
*
596
/*[IF JAVA_SPEC_VERSION >= 14]
597
* @exception UnsupportedOperationException
598
/*[ENDIF] JAVA_SPEC_VERSION >= 14
599
*
600
* @deprecated The semantics of this method are poorly defined and it uses the deprecated suspend() method.
601
*/
602
/*[IF JAVA_SPEC_VERSION >= 11]*/
603
@Deprecated(forRemoval=true, since="1.2")
604
/*[ELSE] JAVA_SPEC_VERSION >= 11 */
605
@Deprecated
606
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
607
public int countStackFrames() {
608
/*[IF JAVA_SPEC_VERSION >= 14]*/
609
throw new UnsupportedOperationException();
610
/*[ELSE] JAVA_SPEC_VERSION >= 14 */
611
return 0;
612
/*[ENDIF] JAVA_SPEC_VERSION >= 14 */
613
}
614
615
/**
616
* Answers the instance of Thread that corresponds to the running Thread
617
* which calls this method.
618
*
619
* @return a java.lang.Thread corresponding to the code that called <code>currentThread()</code>
620
*/
621
public static native Thread currentThread();
622
623
/*[IF JAVA_SPEC_VERSION < 11]*/
624
/**
625
* Destroys the receiver without any monitor cleanup. Not implemented.
626
*
627
* @deprecated May cause deadlocks.
628
*/
629
/*[IF Sidecar19-SE]*/
630
@Deprecated(forRemoval=true, since="1.5")
631
/*[ELSE]*/
632
@Deprecated
633
/*[ENDIF]*/
634
public void destroy() {
635
/*[PR 121318] Should throw NoSuchMethodError */
636
throw new NoSuchMethodError();
637
}
638
/*[ENDIF] JAVA_SPEC_VERSION < 11 */
639
640
/**
641
* Prints a text representation of the stack for this Thread.
642
*/
643
public static void dumpStack() {
644
new Throwable().printStackTrace();
645
}
646
647
/**
648
* Copies an array with all Threads which are in the same ThreadGroup as
649
* the receiver - and subgroups - into the array <code>threads</code>
650
* passed as parameter. If the array passed as parameter is too small no
651
* exception is thrown - the extra elements are simply not copied.
652
*
653
* @param threads array into which the Threads will be copied
654
*
655
* @return How many Threads were copied over
656
*
657
* @exception SecurityException
658
* if the installed SecurityManager fails <code>checkAccess(Ljava.lang.Thread;)</code>
659
*
660
* @see java.lang.SecurityException
661
* @see java.lang.SecurityManager
662
*/
663
public static int enumerate(Thread[] threads) {
664
return currentThread().getThreadGroup().enumerate(threads, true);
665
}
666
667
668
/**
669
* Returns the context ClassLoader for the receiver.
670
*
671
* @return ClassLoader The context ClassLoader
672
*
673
* @see java.lang.ClassLoader
674
* @see #getContextClassLoader()
675
*/
676
@CallerSensitive
677
public ClassLoader getContextClassLoader() {
678
/*[PR 1FCA807]*/
679
/*[PR 1FDTAMT] use callerClassLoader()*/
680
@SuppressWarnings("removal")
681
SecurityManager currentManager = System.getSecurityManager();
682
// if there is a security manager...
683
if (currentManager != null) {
684
ClassLoader callerClassLoader = ClassLoader.callerClassLoader();
685
if (ClassLoader.needsClassLoaderPermissionCheck(callerClassLoader, contextClassLoader)) {
686
currentManager.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
687
}
688
}
689
return contextClassLoader;
690
}
691
692
/**
693
* Answers the name of the receiver.
694
*
695
* @return the receiver's name (a java.lang.String)
696
*/
697
public final String getName() {
698
/*[PR 1FIGT59] Return name as a String. If null, return "null" */
699
return String.valueOf(name);
700
}
701
702
/**
703
* Answers the priority of the receiver.
704
*
705
* @return the receiver's priority (an <code>int</code>)
706
*
707
* @see Thread#setPriority
708
*/
709
public final int getPriority() {
710
return priority;
711
}
712
713
/**
714
* Answers the ThreadGroup to which the receiver belongs
715
*
716
* @return the receiver's ThreadGroup
717
*/
718
public final ThreadGroup getThreadGroup() {
719
return group;
720
}
721
722
723
/**
724
* Posts an interrupt request to the receiver
725
*
726
/*[IF JAVA_SPEC_VERSION >= 14]
727
* From Java 14, the interrupt state for threads that are not alive is tracked.
728
/*[ENDIF] JAVA_SPEC_VERSION >= 14
729
*
730
* @exception SecurityException
731
* if <code>group.checkAccess()</code> fails with a SecurityException
732
*
733
* @see java.lang.SecurityException
734
* @see java.lang.SecurityManager
735
* @see Thread#interrupted
736
* @see Thread#isInterrupted
737
*/
738
public void interrupt() {
739
@SuppressWarnings("removal")
740
SecurityManager currentManager = System.getSecurityManager();
741
742
if (currentManager != null) {
743
if (currentThread() != this) {
744
currentManager.checkAccess(this);
745
}
746
}
747
748
synchronized (lock) {
749
interruptImpl();
750
Interruptible localBlockOn = blockOn;
751
if (localBlockOn != null) {
752
localBlockOn.interrupt(this);
753
}
754
}
755
}
756
757
758
/**
759
* Answers a <code>boolean</code> indicating whether the current Thread
760
* (<code>currentThread()</code>) has a pending interrupt request
761
* (<code>true</code>) or not (<code>false</code>). It also has the
762
* side-effect of clearing the flag.
763
*
764
* @return a <code>boolean</code>
765
*
766
* @see Thread#currentThread
767
* @see Thread#interrupt
768
* @see Thread#isInterrupted
769
*/
770
public static native boolean interrupted();
771
772
/**
773
* Posts an interrupt request to the receiver
774
*
775
/*[IF JAVA_SPEC_VERSION >= 14]
776
* From Java 14, the interrupt state for threads that are not alive is tracked.
777
/*[ENDIF] JAVA_SPEC_VERSION >= 14
778
*
779
* @see Thread#interrupted
780
* @see Thread#isInterrupted
781
*/
782
private native void interruptImpl();
783
784
/**
785
* Answers <code>true</code> if the receiver has
786
* already been started and still runs code (hasn't died yet).
787
* Answers <code>false</code> either if the receiver hasn't been
788
* started yet or if it has already started and run to completion and died.
789
*
790
* @return a <code>boolean</code>
791
*
792
* @see Thread#start
793
*/
794
public final boolean isAlive() {
795
synchronized (lock) {
796
/*[PR CMVC 88976] the Thread is alive until cleanup() is called */
797
return threadRef != NO_REF;
798
}
799
}
800
801
/*[PR 1FJMO7Q] A Thread can be !isAlive() and still be in its ThreadGroup */
802
/**
803
* Answers <code>true</code> if the receiver has
804
* already died and been removed from the ThreadGroup
805
* where it belonged.
806
*
807
* @return a <code>boolean</code>
808
*
809
* @see Thread#start
810
* @see Thread#isAlive
811
*/
812
private boolean isDead() {
813
// Has already started, is not alive anymore, and has been removed from the ThreadGroup
814
synchronized(lock) {
815
return started && threadRef == NO_REF;
816
}
817
}
818
819
/**
820
* Answers a <code>boolean</code> indicating whether the receiver
821
* is a daemon Thread (<code>true</code>) or not (<code>false</code>)
822
* A daemon Thread only runs as long as there are non-daemon Threads
823
* running. When the last non-daemon Thread ends, the whole program ends
824
* no matter if it had daemon Threads still running or not.
825
*
826
* @return a <code>boolean</code>
827
*
828
* @see Thread#setDaemon
829
*/
830
public final boolean isDaemon() {
831
return this.isDaemon;
832
}
833
834
/**
835
* Answers a <code>boolean</code> indicating whether the receiver
836
* has a pending interrupt request (<code>true</code>) or not (<code>false</code>)
837
*
838
* @return a <code>boolean</code>
839
*
840
* @see Thread#interrupt
841
* @see Thread#interrupted
842
*/
843
public boolean isInterrupted() {
844
synchronized(lock) {
845
return isInterruptedImpl();
846
}
847
}
848
849
private native boolean isInterruptedImpl();
850
851
852
/**
853
* Blocks the current Thread (<code>Thread.currentThread()</code>) until the
854
* receiver finishes its execution and dies.
855
*
856
* @exception InterruptedException
857
* if <code>interrupt()</code> was called for the receiver while
858
* it was in the <code>join()</code> call
859
*
860
* @see Object#notifyAll
861
* @see java.lang.ThreadDeath
862
*/
863
public final synchronized void join() throws InterruptedException {
864
if (started)
865
while (!isDead())
866
wait(0);
867
}
868
869
/**
870
* Blocks the current Thread (<code>Thread.currentThread()</code>) until the
871
* receiver finishes its execution and dies or the specified timeout expires, whatever
872
* happens first.
873
*
874
* @param timeoutInMilliseconds The maximum time to wait (in milliseconds).
875
*
876
* @exception InterruptedException
877
* if <code>interrupt()</code> was called for the receiver while
878
* it was in the <code>join()</code> call
879
*
880
* @see Object#notifyAll
881
* @see java.lang.ThreadDeath
882
*/
883
public final void join(long timeoutInMilliseconds) throws InterruptedException {
884
join(timeoutInMilliseconds, 0);
885
}
886
887
/**
888
* Blocks the current Thread (<code>Thread.currentThread()</code>) until the
889
* receiver finishes its execution and dies or the specified timeout expires, whatever
890
* happens first.
891
*
892
* @param timeoutInMilliseconds The maximum time to wait (in milliseconds).
893
* @param nanos Extra nanosecond precision
894
*
895
* @exception InterruptedException
896
* if <code>interrupt()</code> was called for the receiver while
897
* it was in the <code>join()</code> call
898
*
899
* @see Object#notifyAll
900
* @see java.lang.ThreadDeath
901
*/
902
public final synchronized void join(long timeoutInMilliseconds, int nanos) throws InterruptedException {
903
if (timeoutInMilliseconds < 0 || nanos < 0 || nanos > NANOS_MAX)
904
throw new IllegalArgumentException();
905
906
if (!started || isDead()) return;
907
908
// No nanosecond precision for now, we would need something like 'currentTimenanos'
909
910
long totalWaited = 0;
911
long toWait = timeoutInMilliseconds;
912
boolean timedOut = false;
913
914
/*[PR 1PQM757] Even though we do not have nano precision, we cannot wait(0) when any one of the parameters is not zero */
915
if (timeoutInMilliseconds == 0 & nanos > 0) {
916
// We either round up (1 millisecond) or down (no need to wait, just return)
917
if (nanos < 500000)
918
timedOut = true;
919
else
920
toWait = 1;
921
}
922
/*[PR 1FJMO7Q] A Thread can be !isAlive() and still be in its ThreadGroup. Use isDead() */
923
while (!timedOut && !isDead()) {
924
long start = System.currentTimeMillis();
925
wait(toWait);
926
long waited = System.currentTimeMillis() - start;
927
totalWaited+= waited;
928
toWait -= waited;
929
// Anyone could do a synchronized/notify on this thread, so if we wait
930
// less than the timeout, we must check if the thread really died
931
timedOut = (totalWaited >= timeoutInMilliseconds);
932
}
933
934
}
935
936
/**
937
* Private method that generates Thread names that comply with the Java specification
938
*
939
* @version initial
940
*
941
* @return a java.lang.String representing a name for the next Thread being generated
942
*
943
* @see Thread#createCount
944
*/
945
private synchronized static String newName() {
946
/*[PR 97331] Initial thread name should be Thread-0 */
947
if (createCount == -1) {
948
createCount++;
949
return "main"; //$NON-NLS-1$
950
} else {
951
return "Thread-" + createCount++; //$NON-NLS-1$
952
}
953
}
954
955
/**
956
* This is a no-op if the receiver was never suspended, or suspended and already
957
* resumed. If the receiver is suspended, however, makes it resume to the point
958
* where it was when it was suspended.
959
*
960
* @exception SecurityException
961
* if <code>checkAccess()</code> fails with a SecurityException
962
*
963
* @see Thread#suspend()
964
*
965
* @deprecated Used with deprecated method Thread.suspend().
966
*/
967
/*[IF JAVA_SPEC_VERSION >= 11]*/
968
/*[IF JAVA_SPEC_VERSION >= 14]*/
969
@Deprecated(forRemoval=true, since="1.2")
970
/*[ELSE] JAVA_SPEC_VERSION >= 14 */
971
@Deprecated(forRemoval=false, since="1.2")
972
/*[ENDIF] JAVA_SPEC_VERSION >= 14 */
973
/*[ELSE] JAVA_SPEC_VERSION >= 11 */
974
@Deprecated
975
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
976
public final void resume() {
977
checkAccess();
978
synchronized(lock) {
979
resumeImpl();
980
}
981
}
982
983
/**
984
* Private method for the VM to do the actual work of resuming the Thread
985
*
986
*/
987
private native void resumeImpl();
988
989
/**
990
* Calls the <code>run()</code> method of the Runnable object the receiver holds.
991
* If no Runnable is set, does nothing.
992
*
993
* @see Thread#start
994
*/
995
public void run() {
996
if (runnable != null) {
997
runnable.run();
998
}
999
}
1000
1001
/**
1002
* Set the context ClassLoader for the receiver.
1003
*
1004
* @param cl The context ClassLoader
1005
*
1006
* @see java.lang.ClassLoader
1007
* @see #getContextClassLoader()
1008
*/
1009
public void setContextClassLoader(ClassLoader cl) {
1010
/*[PR 1FCA807]*/
1011
@SuppressWarnings("removal")
1012
SecurityManager currentManager = System.getSecurityManager();
1013
// if there is a security manager...
1014
if (currentManager != null) {
1015
// then check permission
1016
currentManager.checkPermission(com.ibm.oti.util.RuntimePermissions.permissionSetContextClassLoader);
1017
}
1018
contextClassLoader = cl;
1019
}
1020
1021
/**
1022
* Set if the receiver is a daemon Thread or not. This can only be done
1023
* before the Thread starts running.
1024
*
1025
* @param isDaemon A boolean indicating if the Thread should be daemon or not
1026
*
1027
* @exception SecurityException
1028
* if <code>checkAccess()</code> fails with a SecurityException
1029
*
1030
* @see Thread#isDaemon
1031
*/
1032
public final void setDaemon(boolean isDaemon) {
1033
checkAccess();
1034
synchronized(lock) {
1035
if (!this.started) {
1036
this.isDaemon = isDaemon;
1037
} else {
1038
/*[PR CVMC 82531] Only throw IllegalThreadStateException if the thread is alive */
1039
if (isAlive()) {
1040
throw new IllegalThreadStateException();
1041
}
1042
}
1043
}
1044
}
1045
1046
/**
1047
* Sets the name of the receiver.
1048
*
1049
* @param threadName new name for the Thread
1050
*
1051
* @exception SecurityException
1052
* if <code>checkAccess()</code> fails with a SecurityException
1053
*
1054
* @see Thread#getName
1055
*/
1056
public final void setName(String threadName) {
1057
checkAccess();
1058
/*[PR 1FIGT59]*/
1059
if (threadName == null) {
1060
throw new NullPointerException();
1061
}
1062
synchronized(lock) {
1063
if (started && threadRef != NO_REF) {
1064
setNameImpl(threadRef, threadName);
1065
}
1066
name = threadName;
1067
}
1068
}
1069
1070
private native void setNameImpl(long threadRef, String threadName);
1071
1072
/**
1073
* Sets the priority of the receiver. Note that the final priority set may be less than the
1074
* requested value, as it is bounded by the maxPriority() of the receiver's ThreadGroup.
1075
*
1076
* @param requestedPriority new priority for the Thread
1077
*
1078
* @exception SecurityException
1079
* if <code>checkAccess()</code> fails with a SecurityException
1080
* @exception IllegalArgumentException
1081
* if the new priority is greater than Thread.MAX_PRIORITY or less than
1082
* Thread.MIN_PRIORITY
1083
*
1084
* @see Thread#getPriority
1085
*/
1086
public final void setPriority(int requestedPriority){
1087
checkAccess();
1088
if (MIN_PRIORITY <= requestedPriority && requestedPriority <= MAX_PRIORITY) {
1089
ThreadGroup myThreadGroup = getThreadGroup();
1090
if (null != myThreadGroup) { /* [PR 134167 Ignore dead threads. */
1091
int finalPriority = requestedPriority;
1092
int threadGroupMaxPriority = myThreadGroup.getMaxPriority();
1093
if (threadGroupMaxPriority < requestedPriority) {
1094
finalPriority = threadGroupMaxPriority;
1095
}
1096
priority = finalPriority;
1097
synchronized(lock) {
1098
/*[PR CMVC 113440] java/lang/Thread/setPriority() Blocks GC */
1099
if (started && (NO_REF != threadRef)) {
1100
setPriorityNoVMAccessImpl(threadRef, finalPriority);
1101
}
1102
}
1103
}
1104
return;
1105
}
1106
throw new IllegalArgumentException();
1107
}
1108
1109
/**
1110
* Private method to tell the VM that the priority for the receiver is changing.
1111
*
1112
* @param priority new priority for the Thread
1113
*
1114
* @see Thread#setPriority
1115
*/
1116
private native void setPriorityNoVMAccessImpl(long threadRef, int priority);
1117
1118
/**
1119
* Causes the thread which sent this message to sleep an interval
1120
* of time (given in milliseconds). The precision is not guaranteed -
1121
* the Thread may sleep more or less than requested.
1122
*
1123
* @param time The time to sleep in milliseconds.
1124
*
1125
* @exception InterruptedException
1126
* if <code>interrupt()</code> was called for this Thread while it was sleeping
1127
*
1128
* @see Thread#interrupt()
1129
*/
1130
1131
public static void sleep(long time) throws InterruptedException {
1132
sleep(time, 0);
1133
}
1134
1135
/**
1136
* Causes the thread which sent this message to sleep an interval
1137
* of time (given in milliseconds). The precision is not guaranteed -
1138
* the Thread may sleep more or less than requested.
1139
*
1140
* @param time The time to sleep in milliseconds.
1141
* @param nanos Extra nanosecond precision
1142
*
1143
* @exception InterruptedException
1144
* if <code>interrupt()</code> was called for this Thread while it was sleeping
1145
*
1146
* @see Thread#interrupt()
1147
*/
1148
public static native void sleep(long time, int nanos) throws InterruptedException;
1149
1150
/*[IF Sidecar19-SE]*/
1151
/**
1152
* Hints to the run-time that a spin loop is being performed
1153
* which helps the thread in the spin loop not to use as much power.
1154
*
1155
*/
1156
public static native void onSpinWait();
1157
/*[ENDIF]*/
1158
1159
/**
1160
* Starts the new Thread of execution. The <code>run()</code> method of the receiver
1161
* will be called by the receiver Thread itself (and not the Thread calling <code>start()</code>).
1162
*
1163
* @exception IllegalThreadStateException
1164
* Unspecified in the Java language specification
1165
*
1166
* @see Thread#run
1167
*/
1168
public synchronized void start() {
1169
boolean success = false;
1170
1171
/*[PR CMVC 189553] Deadlock when a thread fails to start and another thread is ins */
1172
/*[IF]
1173
* Deadlock happens when a thread is added to the ThreadGroup
1174
* and its start method fails and calls its ThreadGroup's remove method for this thread to be removed while holding this thread's lock.
1175
* If there is another call which is holding ThreadGroup's child lock and waiting for this thread's lock,
1176
* then deadlock occurs since ThreadGroup's remove method is waiting for its child lock.
1177
*
1178
* Release the lock before calling threadgroup's remove method for this thread.
1179
/*[ENDIF]*/
1180
if (started) {
1181
/*[MSG "K0341", "Thread is already started"]*/
1182
throw new IllegalThreadStateException(com.ibm.oti.util.Msg.getString("K0341")); //$NON-NLS-1$
1183
}
1184
/*[PR 115667, CMVC 94448] In 1.5, thread is added to ThreadGroup when started */
1185
group.add(this);
1186
1187
try {
1188
synchronized (lock) {
1189
startImpl();
1190
success = true;
1191
}
1192
} finally {
1193
if (!success) {
1194
group.remove(this);
1195
}
1196
}
1197
}
1198
1199
private native void startImpl();
1200
1201
/**
1202
* Requests the receiver Thread to stop and throw ThreadDeath.
1203
* The Thread is resumed if it was suspended and awakened if it was
1204
* sleeping, so that it can proceed to throw ThreadDeath.
1205
*
1206
* @exception SecurityException
1207
* if <code>checkAccess()</code> fails with a SecurityException
1208
*
1209
* @deprecated
1210
*/
1211
/*[IF JAVA_SPEC_VERSION >= 18]*/
1212
@Deprecated(forRemoval=true, since="1.2")
1213
/*[ELSEIF JAVA_SPEC_VERSION >= 9]*/
1214
@Deprecated(forRemoval=false, since="1.2")
1215
/*[ELSE]*/
1216
@Deprecated
1217
/*[ENDIF]*/
1218
public final void stop() {
1219
/*[PR CMVC 94728] AccessControlException on dead Thread */
1220
/* the only case we don't want to do the check is if the thread has been started but is now dead */
1221
if (!isDead()){
1222
stopWithThrowable(new ThreadDeath());
1223
}
1224
}
1225
1226
/*[IF JAVA_SPEC_VERSION < 11]*/
1227
/**
1228
* Throws UnsupportedOperationException.
1229
*
1230
* @param throwable Throwable object to be thrown by the Thread
1231
*
1232
* @deprecated
1233
*/
1234
/*[IF Sidecar19-SE]*/
1235
@Deprecated(forRemoval=true, since="1.2")
1236
/*[ELSE]*/
1237
@Deprecated
1238
/*[ENDIF]*/
1239
public final void stop(Throwable throwable) {
1240
throw new UnsupportedOperationException();
1241
}
1242
/*[ENDIF] JAVA_SPEC_VERSION < 11 */
1243
1244
private final synchronized void stopWithThrowable(Throwable throwable) {
1245
checkAccess();
1246
/*[PR 95390]*/
1247
if ((currentThread() != this) || !(throwable instanceof ThreadDeath)) {
1248
@SuppressWarnings("removal")
1249
SecurityManager currentManager = System.getSecurityManager();
1250
if (currentManager != null) {
1251
currentManager.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
1252
}
1253
}
1254
1255
synchronized (lock) {
1256
if (throwable != null) {
1257
if (!started) {
1258
/* [PR CMVC 179978] Java7:JCK:java_lang.Thread fails in all plat*/
1259
/*
1260
* if the thread has not yet been simply store the fact that stop has been called
1261
* The JVM uses this to determine if stop has been called before start
1262
*/
1263
stopCalled = true;
1264
} else {
1265
/* thread was started so do the full stop */
1266
stopImpl(throwable);
1267
}
1268
} else {
1269
throw new NullPointerException();
1270
}
1271
}
1272
}
1273
1274
/**
1275
* Private method for the VM to do the actual work of stopping the Thread
1276
*
1277
* @param throwable Throwable object to be thrown by the Thread
1278
*/
1279
private native void stopImpl(Throwable throwable);
1280
1281
/**
1282
* This is a no-op if the receiver is suspended. If the receiver <code>isAlive()</code>
1283
* however, suspended it until <code>resume()</code> is sent to it. Suspend requests
1284
* are not queued, which means that N requests are equivalent to just one - only one
1285
* resume request is needed in this case.
1286
*
1287
* @exception SecurityException
1288
* if <code>checkAccess()</code> fails with a SecurityException
1289
*
1290
* @see Thread#resume()
1291
*
1292
* @deprecated May cause deadlocks.
1293
*/
1294
/*[IF JAVA_SPEC_VERSION >= 11]*/
1295
/*[IF JAVA_SPEC_VERSION >= 14]*/
1296
@Deprecated(forRemoval=true, since="1.2")
1297
/*[ELSE] JAVA_SPEC_VERSION >= 14 */
1298
@Deprecated(forRemoval=false, since="1.2")
1299
/*[ENDIF] JAVA_SPEC_VERSION >= 14 */
1300
/*[ELSE] JAVA_SPEC_VERSION >= 11 */
1301
@Deprecated
1302
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
1303
public final void suspend() {
1304
checkAccess();
1305
/*[PR 106321]*/
1306
if (currentThread() == this) {
1307
suspendImpl();
1308
} else {
1309
synchronized (lock) {
1310
suspendImpl();
1311
}
1312
}
1313
}
1314
1315
/**
1316
* Private method for the VM to do the actual work of suspending the Thread
1317
*
1318
* Conceptually this method can't be synchronized or a Thread that suspends itself will
1319
* do so with the Thread's lock and this will cause deadlock to valid Java programs.
1320
*/
1321
private native void suspendImpl();
1322
1323
/*[PR 97801]*/
1324
/**
1325
* Answers a string containing a concise, human-readable
1326
* description of the receiver.
1327
*
1328
* @return a printable representation for the receiver.
1329
*/
1330
public String toString() {
1331
/*[PR JAZZ 85499] : NullPointerException from Thread.toString() */
1332
ThreadGroup localGroup = getThreadGroup();
1333
1334
return "Thread[" + this.getName() + "," + this.getPriority() + "," + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1335
/*[PR 97317] Handle a null thread group */
1336
(null == localGroup ? "" : localGroup.getName()) + "]" ; //$NON-NLS-1$ //$NON-NLS-2$
1337
}
1338
1339
/**
1340
* Causes the thread which sent this message to yield execution to another Thread
1341
* that is ready to run. The actual scheduling is implementation-dependent.
1342
*
1343
* @version initial
1344
*/
1345
public static native void yield();
1346
1347
/**
1348
* Returns whether the current thread has a monitor lock on the specified object.
1349
*
1350
* @param object the object to test for the monitor lock
1351
* @return true when the current thread has a monitor lock on the specified object
1352
*
1353
* @since 1.4
1354
*/
1355
public static native boolean holdsLock(Object object);
1356
1357
/*[IF JAVA_SPEC_VERSION >= 11]*/
1358
static
1359
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
1360
void blockedOn(Interruptible interruptible) {
1361
Thread currentThread;
1362
/*[IF JAVA_SPEC_VERSION >= 11]*/
1363
currentThread = currentThread();
1364
/*[ELSE] JAVA_SPEC_VERSION >= 11
1365
currentThread = this;
1366
/*[ENDIF] JAVA_SPEC_VERSION >= 11 */
1367
synchronized (currentThread.lock) {
1368
currentThread.blockOn = interruptible;
1369
}
1370
}
1371
1372
1373
private native Throwable getStackTraceImpl();
1374
1375
/**
1376
* Returns an array of StackTraceElement, where each element of the array represents a frame
1377
* on the Java stack.
1378
*
1379
* @return an array of StackTraceElement
1380
*
1381
* @throws SecurityException if the RuntimePermission "getStackTrace" is not allowed
1382
*
1383
* @see java.lang.StackTraceElement
1384
*/
1385
public StackTraceElement[] getStackTrace() {
1386
if (Thread.currentThread() != this) {
1387
@SuppressWarnings("removal")
1388
SecurityManager security = System.getSecurityManager();
1389
if (security != null) {
1390
security.checkPermission(SecurityConstants.GET_STACK_TRACE_PERMISSION); //$NON-NLS-1$
1391
}
1392
}
1393
Throwable t;
1394
1395
synchronized (lock) {
1396
if (!isAlive()) {
1397
return EMPTY_STACK_TRACE;
1398
}
1399
t = getStackTraceImpl();
1400
}
1401
return J9VMInternals.getStackTrace(t, false);
1402
}
1403
1404
/**
1405
* Returns a Map containing Thread keys, and values which are arrays of StackTraceElement. The Map contains
1406
* all Threads which were alive at the time this method was called.
1407
*
1408
* @return an array of StackTraceElement
1409
*
1410
* @throws SecurityException if the RuntimePermission "getStackTrace" is not allowed, or the
1411
* RuntimePermission "modifyThreadGroup" is not allowed
1412
*
1413
* @see #getStackTrace()
1414
*/
1415
public static Map<Thread, StackTraceElement[]> getAllStackTraces() {
1416
@SuppressWarnings("removal")
1417
SecurityManager security = System.getSecurityManager();
1418
if (security != null) {
1419
security.checkPermission(SecurityConstants.GET_STACK_TRACE_PERMISSION);
1420
security.checkPermission(SecurityConstants.MODIFY_THREADGROUP_PERMISSION);
1421
}
1422
// Allow room for more Threads to be created before calling enumerate()
1423
int count = systemThreadGroup.activeCount() + 20;
1424
Thread[] threads = new Thread[count];
1425
count = systemThreadGroup.enumerate(threads);
1426
Map<Thread, StackTraceElement[]> result = new java.util.HashMap<>(count);
1427
for (int i = 0; i < count; i++) {
1428
result.put(threads[i], threads[i].getStackTrace());
1429
}
1430
return result;
1431
}
1432
1433
/**
1434
* Return a unique id for this Thread.
1435
*
1436
* @return a positive unique id for this Thread.
1437
*/
1438
public long getId() {
1439
return tid;
1440
}
1441
1442
/**
1443
* A handler which is invoked when an uncaught exception occurs in a Thread.
1444
*/
1445
@FunctionalInterface
1446
public static interface UncaughtExceptionHandler {
1447
/**
1448
* The method invoked when an uncaught exception occurs in a Thread.
1449
*
1450
* @param thread the Thread where the uncaught exception occurred
1451
* @param throwable the uncaught exception
1452
*/
1453
public void uncaughtException(Thread thread, Throwable throwable) ;
1454
}
1455
1456
/**
1457
* Return the UncaughtExceptionHandler for this Thread.
1458
*
1459
* @return the UncaughtExceptionHandler for this Thread
1460
*
1461
* @see UncaughtExceptionHandler
1462
*/
1463
public UncaughtExceptionHandler getUncaughtExceptionHandler() {
1464
if (exceptionHandler == null)
1465
return getThreadGroup();
1466
return exceptionHandler;
1467
}
1468
1469
/**
1470
* Set the UncaughtExceptionHandler for this Thread.
1471
*
1472
* @param handler the UncaughtExceptionHandler to set
1473
*
1474
* @see UncaughtExceptionHandler
1475
*/
1476
public void setUncaughtExceptionHandler(UncaughtExceptionHandler handler) {
1477
exceptionHandler = handler;
1478
}
1479
1480
/**
1481
* Return the default UncaughtExceptionHandler used for new Threads.
1482
*
1483
* @return the default UncaughtExceptionHandler for new Threads
1484
*
1485
* @see UncaughtExceptionHandler
1486
*/
1487
public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() {
1488
return defaultExceptionHandler;
1489
}
1490
1491
/**
1492
* Set the UncaughtExceptionHandler used for new Threads.
1493
*
1494
* @param handler the UncaughtExceptionHandler to set
1495
*
1496
* @see UncaughtExceptionHandler
1497
*/
1498
public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler handler) {
1499
SecurityManager security = System.getSecurityManager();
1500
if (security != null)
1501
security.checkPermission(com.ibm.oti.util.RuntimePermissions.permissionSetDefaultUncaughtExceptionHandler);
1502
defaultExceptionHandler = handler;
1503
}
1504
1505
/**
1506
* The possible Thread states.
1507
*/
1508
// The order of the States is known by the getStateImpl() native
1509
public static enum State {
1510
/**
1511
* A Thread which has not yet started.
1512
*/
1513
NEW,
1514
/**
1515
* A Thread which is running or suspended.
1516
*/
1517
RUNNABLE,
1518
/**
1519
* A Thread which is blocked on a monitor.
1520
*/
1521
BLOCKED,
1522
/**
1523
* A Thread which is waiting with no timeout.
1524
*/
1525
WAITING,
1526
/**
1527
* A Thread which is waiting with a timeout.
1528
*/
1529
TIMED_WAITING,
1530
/**
1531
* A thread which is no longer alive.
1532
*/
1533
TERMINATED }
1534
1535
/**
1536
* Returns the current Thread state.
1537
*
1538
* @return the current Thread state constant.
1539
*
1540
* @see State
1541
*/
1542
public State getState() {
1543
synchronized(lock) {
1544
if (threadRef == NO_REF) {
1545
if (isDead()) {
1546
return State.TERMINATED;
1547
}
1548
return State.NEW;
1549
}
1550
return State.values()[getStateImpl(threadRef)];
1551
}
1552
}
1553
1554
private native int getStateImpl(long threadRef);
1555
1556
/**
1557
* Any uncaught exception in any Thread has to be forwarded (by the VM) to the Thread's ThreadGroup
1558
* by sending this message (uncaughtException). This allows users to define custom ThreadGroup classes
1559
* and custom behavior for when a Thread has an uncaughtException or when it does (ThreadDeath).
1560
*
1561
* @version initial
1562
*
1563
* @param e The uncaught exception itself
1564
*
1565
* @see Thread#stop()
1566
* @see Thread#stop(Throwable)
1567
* @see ThreadDeath
1568
*/
1569
void uncaughtException(Throwable e) {
1570
UncaughtExceptionHandler handler = getUncaughtExceptionHandler();
1571
if (handler != null)
1572
handler.uncaughtException(this, e);
1573
}
1574
1575
/**
1576
* Called by J9VMInternals.threadCleanup() so the Thread can release resources
1577
* and change its state.
1578
*
1579
* @see J9VMInternals#threadCleanup()
1580
*/
1581
void cleanup() {
1582
/*[IF JAVA_SPEC_VERSION >= 14]*/
1583
/* Refresh deadInterrupt value so it is accurate when thread reference is removed. */
1584
deadInterrupt = interrupted();
1585
/*[ENDIF] JAVA_SPEC_VERSION >= 14 */
1586
1587
/*[IF Sidecar18-SE-OpenJ9]*/
1588
if ((threadLocals != null) && TerminatingThreadLocal.REGISTRY.isPresent()) {
1589
TerminatingThreadLocal.threadTerminated();
1590
}
1591
/*[ENDIF] Sidecar18-SE-OpenJ9 */
1592
1593
/*[PR 97317]*/
1594
group = null;
1595
1596
/*[PR CVMC 118827] references are not removed in dead threads */
1597
runnable = null;
1598
inheritedAccessControlContext = null;
1599
1600
threadLocals = null;
1601
inheritableThreadLocals = null;
1602
1603
synchronized(lock) {
1604
threadRef = Thread.NO_REF; // So that isAlive() can work
1605
}
1606
}
1607
1608
// prevent subclasses from becoming Cloneable
1609
protected Object clone() throws CloneNotSupportedException {
1610
throw new CloneNotSupportedException();
1611
}
1612
1613
}
1614
1615