author | never |
Mon, 12 Jul 2010 22:27:18 -0700 | |
changeset 5926 | a36f90d986b6 |
parent 5506 | 202f599c92aa |
child 6866 | 4197c5af089d |
child 6316 | 6d91c1ceac26 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
5506 | 2 |
* Copyright (c) 1994, 2009, Oracle and/or its affiliates. All rights reserved. |
2 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 10 |
* |
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
5506 | 21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
2 | 24 |
*/ |
25 |
||
26 |
package java.lang; |
|
27 |
||
2069
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
28 |
import java.lang.ref.Reference; |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
29 |
import java.lang.ref.ReferenceQueue; |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
30 |
import java.lang.ref.WeakReference; |
2 | 31 |
import java.security.AccessController; |
32 |
import java.security.AccessControlContext; |
|
33 |
import java.security.PrivilegedAction; |
|
34 |
import java.util.Map; |
|
35 |
import java.util.HashMap; |
|
2069
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
36 |
import java.util.concurrent.ConcurrentHashMap; |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
37 |
import java.util.concurrent.ConcurrentMap; |
2 | 38 |
import java.util.concurrent.locks.LockSupport; |
39 |
import sun.nio.ch.Interruptible; |
|
40 |
import sun.security.util.SecurityConstants; |
|
41 |
||
42 |
||
43 |
/** |
|
44 |
* A <i>thread</i> is a thread of execution in a program. The Java |
|
45 |
* Virtual Machine allows an application to have multiple threads of |
|
46 |
* execution running concurrently. |
|
47 |
* <p> |
|
48 |
* Every thread has a priority. Threads with higher priority are |
|
49 |
* executed in preference to threads with lower priority. Each thread |
|
50 |
* may or may not also be marked as a daemon. When code running in |
|
51 |
* some thread creates a new <code>Thread</code> object, the new |
|
52 |
* thread has its priority initially set equal to the priority of the |
|
53 |
* creating thread, and is a daemon thread if and only if the |
|
54 |
* creating thread is a daemon. |
|
55 |
* <p> |
|
56 |
* When a Java Virtual Machine starts up, there is usually a single |
|
57 |
* non-daemon thread (which typically calls the method named |
|
58 |
* <code>main</code> of some designated class). The Java Virtual |
|
59 |
* Machine continues to execute threads until either of the following |
|
60 |
* occurs: |
|
61 |
* <ul> |
|
62 |
* <li>The <code>exit</code> method of class <code>Runtime</code> has been |
|
63 |
* called and the security manager has permitted the exit operation |
|
64 |
* to take place. |
|
65 |
* <li>All threads that are not daemon threads have died, either by |
|
66 |
* returning from the call to the <code>run</code> method or by |
|
67 |
* throwing an exception that propagates beyond the <code>run</code> |
|
68 |
* method. |
|
69 |
* </ul> |
|
70 |
* <p> |
|
71 |
* There are two ways to create a new thread of execution. One is to |
|
72 |
* declare a class to be a subclass of <code>Thread</code>. This |
|
73 |
* subclass should override the <code>run</code> method of class |
|
74 |
* <code>Thread</code>. An instance of the subclass can then be |
|
75 |
* allocated and started. For example, a thread that computes primes |
|
76 |
* larger than a stated value could be written as follows: |
|
77 |
* <p><hr><blockquote><pre> |
|
78 |
* class PrimeThread extends Thread { |
|
79 |
* long minPrime; |
|
80 |
* PrimeThread(long minPrime) { |
|
81 |
* this.minPrime = minPrime; |
|
82 |
* } |
|
83 |
* |
|
84 |
* public void run() { |
|
85 |
* // compute primes larger than minPrime |
|
86 |
* . . . |
|
87 |
* } |
|
88 |
* } |
|
89 |
* </pre></blockquote><hr> |
|
90 |
* <p> |
|
91 |
* The following code would then create a thread and start it running: |
|
92 |
* <p><blockquote><pre> |
|
93 |
* PrimeThread p = new PrimeThread(143); |
|
94 |
* p.start(); |
|
95 |
* </pre></blockquote> |
|
96 |
* <p> |
|
97 |
* The other way to create a thread is to declare a class that |
|
98 |
* implements the <code>Runnable</code> interface. That class then |
|
99 |
* implements the <code>run</code> method. An instance of the class can |
|
100 |
* then be allocated, passed as an argument when creating |
|
101 |
* <code>Thread</code>, and started. The same example in this other |
|
102 |
* style looks like the following: |
|
103 |
* <p><hr><blockquote><pre> |
|
104 |
* class PrimeRun implements Runnable { |
|
105 |
* long minPrime; |
|
106 |
* PrimeRun(long minPrime) { |
|
107 |
* this.minPrime = minPrime; |
|
108 |
* } |
|
109 |
* |
|
110 |
* public void run() { |
|
111 |
* // compute primes larger than minPrime |
|
112 |
* . . . |
|
113 |
* } |
|
114 |
* } |
|
115 |
* </pre></blockquote><hr> |
|
116 |
* <p> |
|
117 |
* The following code would then create a thread and start it running: |
|
118 |
* <p><blockquote><pre> |
|
119 |
* PrimeRun p = new PrimeRun(143); |
|
120 |
* new Thread(p).start(); |
|
121 |
* </pre></blockquote> |
|
122 |
* <p> |
|
123 |
* Every thread has a name for identification purposes. More than |
|
124 |
* one thread may have the same name. If a name is not specified when |
|
125 |
* a thread is created, a new name is generated for it. |
|
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
126 |
* <p> |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
127 |
* Unless otherwise noted, passing a {@code null} argument to a constructor |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
128 |
* or method in this class will cause a {@link NullPointerException} to be |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
129 |
* thrown. |
2 | 130 |
* |
131 |
* @author unascribed |
|
132 |
* @see Runnable |
|
133 |
* @see Runtime#exit(int) |
|
134 |
* @see #run() |
|
135 |
* @see #stop() |
|
136 |
* @since JDK1.0 |
|
137 |
*/ |
|
138 |
public |
|
139 |
class Thread implements Runnable { |
|
140 |
/* Make sure registerNatives is the first thing <clinit> does. */ |
|
141 |
private static native void registerNatives(); |
|
142 |
static { |
|
143 |
registerNatives(); |
|
144 |
} |
|
145 |
||
146 |
private char name[]; |
|
147 |
private int priority; |
|
148 |
private Thread threadQ; |
|
149 |
private long eetop; |
|
150 |
||
151 |
/* Whether or not to single_step this thread. */ |
|
152 |
private boolean single_step; |
|
153 |
||
154 |
/* Whether or not the thread is a daemon thread. */ |
|
155 |
private boolean daemon = false; |
|
156 |
||
157 |
/* JVM state */ |
|
158 |
private boolean stillborn = false; |
|
159 |
||
160 |
/* What will be run. */ |
|
161 |
private Runnable target; |
|
162 |
||
163 |
/* The group of this thread */ |
|
164 |
private ThreadGroup group; |
|
165 |
||
166 |
/* The context ClassLoader for this thread */ |
|
167 |
private ClassLoader contextClassLoader; |
|
168 |
||
169 |
/* The inherited AccessControlContext of this thread */ |
|
170 |
private AccessControlContext inheritedAccessControlContext; |
|
171 |
||
172 |
/* For autonumbering anonymous threads. */ |
|
173 |
private static int threadInitNumber; |
|
174 |
private static synchronized int nextThreadNum() { |
|
175 |
return threadInitNumber++; |
|
176 |
} |
|
177 |
||
178 |
/* ThreadLocal values pertaining to this thread. This map is maintained |
|
179 |
* by the ThreadLocal class. */ |
|
180 |
ThreadLocal.ThreadLocalMap threadLocals = null; |
|
181 |
||
182 |
/* |
|
183 |
* InheritableThreadLocal values pertaining to this thread. This map is |
|
184 |
* maintained by the InheritableThreadLocal class. |
|
185 |
*/ |
|
186 |
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; |
|
187 |
||
188 |
/* |
|
189 |
* The requested stack size for this thread, or 0 if the creator did |
|
190 |
* not specify a stack size. It is up to the VM to do whatever it |
|
191 |
* likes with this number; some VMs will ignore it. |
|
192 |
*/ |
|
193 |
private long stackSize; |
|
194 |
||
195 |
/* |
|
196 |
* JVM-private state that persists after native thread termination. |
|
197 |
*/ |
|
198 |
private long nativeParkEventPointer; |
|
199 |
||
200 |
/* |
|
201 |
* Thread ID |
|
202 |
*/ |
|
203 |
private long tid; |
|
204 |
||
205 |
/* For generating thread ID */ |
|
206 |
private static long threadSeqNumber; |
|
207 |
||
208 |
/* Java thread status for tools, |
|
209 |
* initialized to indicate thread 'not yet started' |
|
210 |
*/ |
|
211 |
||
212 |
private int threadStatus = 0; |
|
213 |
||
214 |
||
215 |
private static synchronized long nextThreadID() { |
|
216 |
return ++threadSeqNumber; |
|
217 |
} |
|
218 |
||
219 |
/** |
|
220 |
* The argument supplied to the current call to |
|
221 |
* java.util.concurrent.locks.LockSupport.park. |
|
222 |
* Set by (private) java.util.concurrent.locks.LockSupport.setBlocker |
|
223 |
* Accessed using java.util.concurrent.locks.LockSupport.getBlocker |
|
224 |
*/ |
|
225 |
volatile Object parkBlocker; |
|
226 |
||
227 |
/* The object in which this thread is blocked in an interruptible I/O |
|
228 |
* operation, if any. The blocker's interrupt method should be invoked |
|
229 |
* after setting this thread's interrupt status. |
|
230 |
*/ |
|
231 |
private volatile Interruptible blocker; |
|
232 |
private Object blockerLock = new Object(); |
|
233 |
||
234 |
/* Set the blocker field; invoked via sun.misc.SharedSecrets from java.nio code |
|
235 |
*/ |
|
236 |
void blockedOn(Interruptible b) { |
|
237 |
synchronized (blockerLock) { |
|
238 |
blocker = b; |
|
239 |
} |
|
240 |
} |
|
241 |
||
242 |
/** |
|
243 |
* The minimum priority that a thread can have. |
|
244 |
*/ |
|
245 |
public final static int MIN_PRIORITY = 1; |
|
246 |
||
247 |
/** |
|
248 |
* The default priority that is assigned to a thread. |
|
249 |
*/ |
|
250 |
public final static int NORM_PRIORITY = 5; |
|
251 |
||
252 |
/** |
|
253 |
* The maximum priority that a thread can have. |
|
254 |
*/ |
|
255 |
public final static int MAX_PRIORITY = 10; |
|
256 |
||
257 |
/* If stop was called before start */ |
|
258 |
private boolean stopBeforeStart; |
|
259 |
||
260 |
/* Remembered Throwable from stop before start */ |
|
261 |
private Throwable throwableFromStop; |
|
262 |
||
263 |
/** |
|
264 |
* Returns a reference to the currently executing thread object. |
|
265 |
* |
|
266 |
* @return the currently executing thread. |
|
267 |
*/ |
|
268 |
public static native Thread currentThread(); |
|
269 |
||
270 |
/** |
|
271 |
* A hint to the scheduler that the current thread is willing to yield |
|
272 |
* its current use of a processor. The scheduler is free to ignore this |
|
273 |
* hint. |
|
274 |
* |
|
275 |
* <p> Yield is a heuristic attempt to improve relative progression |
|
276 |
* between threads that would otherwise over-utilise a CPU. Its use |
|
277 |
* should be combined with detailed profiling and benchmarking to |
|
278 |
* ensure that it actually has the desired effect. |
|
279 |
* |
|
280 |
* <p> It is rarely appropriate to use this method. It may be useful |
|
281 |
* for debugging or testing purposes, where it may help to reproduce |
|
282 |
* bugs due to race conditions. It may also be useful when designing |
|
283 |
* concurrency control constructs such as the ones in the |
|
284 |
* {@link java.util.concurrent.locks} package. |
|
285 |
*/ |
|
286 |
public static native void yield(); |
|
287 |
||
288 |
/** |
|
289 |
* Causes the currently executing thread to sleep (temporarily cease |
|
290 |
* execution) for the specified number of milliseconds, subject to |
|
291 |
* the precision and accuracy of system timers and schedulers. The thread |
|
292 |
* does not lose ownership of any monitors. |
|
293 |
* |
|
294 |
* @param millis |
|
295 |
* the length of time to sleep in milliseconds |
|
296 |
* |
|
297 |
* @throws IllegalArgumentException |
|
298 |
* if the value of {@code millis} is negative |
|
299 |
* |
|
300 |
* @throws InterruptedException |
|
301 |
* if any thread has interrupted the current thread. The |
|
302 |
* <i>interrupted status</i> of the current thread is |
|
303 |
* cleared when this exception is thrown. |
|
304 |
*/ |
|
305 |
public static native void sleep(long millis) throws InterruptedException; |
|
306 |
||
307 |
/** |
|
308 |
* Causes the currently executing thread to sleep (temporarily cease |
|
309 |
* execution) for the specified number of milliseconds plus the specified |
|
310 |
* number of nanoseconds, subject to the precision and accuracy of system |
|
311 |
* timers and schedulers. The thread does not lose ownership of any |
|
312 |
* monitors. |
|
313 |
* |
|
314 |
* @param millis |
|
315 |
* the length of time to sleep in milliseconds |
|
316 |
* |
|
317 |
* @param nanos |
|
318 |
* {@code 0-999999} additional nanoseconds to sleep |
|
319 |
* |
|
320 |
* @throws IllegalArgumentException |
|
321 |
* if the value of {@code millis} is negative, or the value of |
|
322 |
* {@code nanos} is not in the range {@code 0-999999} |
|
323 |
* |
|
324 |
* @throws InterruptedException |
|
325 |
* if any thread has interrupted the current thread. The |
|
326 |
* <i>interrupted status</i> of the current thread is |
|
327 |
* cleared when this exception is thrown. |
|
328 |
*/ |
|
329 |
public static void sleep(long millis, int nanos) |
|
330 |
throws InterruptedException { |
|
331 |
if (millis < 0) { |
|
332 |
throw new IllegalArgumentException("timeout value is negative"); |
|
333 |
} |
|
334 |
||
335 |
if (nanos < 0 || nanos > 999999) { |
|
336 |
throw new IllegalArgumentException( |
|
337 |
"nanosecond timeout value out of range"); |
|
338 |
} |
|
339 |
||
340 |
if (nanos >= 500000 || (nanos != 0 && millis == 0)) { |
|
341 |
millis++; |
|
342 |
} |
|
343 |
||
344 |
sleep(millis); |
|
345 |
} |
|
346 |
||
347 |
/** |
|
348 |
* Initializes a Thread. |
|
349 |
* |
|
350 |
* @param g the Thread group |
|
351 |
* @param target the object whose run() method gets called |
|
352 |
* @param name the name of the new Thread |
|
353 |
* @param stackSize the desired stack size for the new thread, or |
|
354 |
* zero to indicate that this parameter is to be ignored. |
|
355 |
*/ |
|
356 |
private void init(ThreadGroup g, Runnable target, String name, |
|
357 |
long stackSize) { |
|
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
358 |
if (name == null) { |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
359 |
throw new NullPointerException("name cannot be null"); |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
360 |
} |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
361 |
|
2 | 362 |
Thread parent = currentThread(); |
363 |
SecurityManager security = System.getSecurityManager(); |
|
364 |
if (g == null) { |
|
365 |
/* Determine if it's an applet or not */ |
|
366 |
||
367 |
/* If there is a security manager, ask the security manager |
|
368 |
what to do. */ |
|
369 |
if (security != null) { |
|
370 |
g = security.getThreadGroup(); |
|
371 |
} |
|
372 |
||
373 |
/* If the security doesn't have a strong opinion of the matter |
|
374 |
use the parent thread group. */ |
|
375 |
if (g == null) { |
|
376 |
g = parent.getThreadGroup(); |
|
377 |
} |
|
378 |
} |
|
379 |
||
380 |
/* checkAccess regardless of whether or not threadgroup is |
|
381 |
explicitly passed in. */ |
|
382 |
g.checkAccess(); |
|
383 |
||
384 |
/* |
|
385 |
* Do we have the required permissions? |
|
386 |
*/ |
|
387 |
if (security != null) { |
|
388 |
if (isCCLOverridden(getClass())) { |
|
389 |
security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); |
|
390 |
} |
|
391 |
} |
|
392 |
||
393 |
g.addUnstarted(); |
|
394 |
||
395 |
this.group = g; |
|
396 |
this.daemon = parent.isDaemon(); |
|
397 |
this.priority = parent.getPriority(); |
|
398 |
this.name = name.toCharArray(); |
|
399 |
if (security == null || isCCLOverridden(parent.getClass())) |
|
400 |
this.contextClassLoader = parent.getContextClassLoader(); |
|
401 |
else |
|
402 |
this.contextClassLoader = parent.contextClassLoader; |
|
403 |
this.inheritedAccessControlContext = AccessController.getContext(); |
|
404 |
this.target = target; |
|
405 |
setPriority(priority); |
|
406 |
if (parent.inheritableThreadLocals != null) |
|
407 |
this.inheritableThreadLocals = |
|
408 |
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); |
|
409 |
/* Stash the specified stack size in case the VM cares */ |
|
410 |
this.stackSize = stackSize; |
|
411 |
||
412 |
/* Set thread ID */ |
|
413 |
tid = nextThreadID(); |
|
414 |
} |
|
415 |
||
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
416 |
/** |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
417 |
* Allocates a new {@code Thread} object. This constructor has the same |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
418 |
* effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
419 |
* {@code (null, null, gname)}, where {@code gname} is a newly generated |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
420 |
* name. Automatically generated names are of the form |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
421 |
* {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer. |
2 | 422 |
*/ |
423 |
public Thread() { |
|
424 |
init(null, null, "Thread-" + nextThreadNum(), 0); |
|
425 |
} |
|
426 |
||
427 |
/** |
|
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
428 |
* Allocates a new {@code Thread} object. This constructor has the same |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
429 |
* effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
430 |
* {@code (null, target, gname)}, where {@code gname} is a newly generated |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
431 |
* name. Automatically generated names are of the form |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
432 |
* {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer. |
2 | 433 |
* |
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
434 |
* @param target |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
435 |
* the object whose {@code run} method is invoked when this thread |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
436 |
* is started. If {@code null}, this classes {@code run} method does |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
437 |
* nothing. |
2 | 438 |
*/ |
439 |
public Thread(Runnable target) { |
|
440 |
init(null, target, "Thread-" + nextThreadNum(), 0); |
|
441 |
} |
|
442 |
||
443 |
/** |
|
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
444 |
* Allocates a new {@code Thread} object. This constructor has the same |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
445 |
* effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
446 |
* {@code (group, target, gname)} ,where {@code gname} is a newly generated |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
447 |
* name. Automatically generated names are of the form |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
448 |
* {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer. |
2 | 449 |
* |
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
450 |
* @param group |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
451 |
* the thread group. If {@code null} and there is a security |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
452 |
* manager, the group is determined by {@linkplain |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
453 |
* SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}. |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
454 |
* If there is not a security manager or {@code |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
455 |
* SecurityManager.getThreadGroup()} returns {@code null}, the group |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
456 |
* is set to the current thread's thread group. |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
457 |
* |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
458 |
* @param target |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
459 |
* the object whose {@code run} method is invoked when this thread |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
460 |
* is started. If {@code null}, this thread's run method is invoked. |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
461 |
* |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
462 |
* @throws SecurityException |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
463 |
* if the current thread cannot create a thread in the specified |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
464 |
* thread group |
2 | 465 |
*/ |
466 |
public Thread(ThreadGroup group, Runnable target) { |
|
467 |
init(group, target, "Thread-" + nextThreadNum(), 0); |
|
468 |
} |
|
469 |
||
470 |
/** |
|
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
471 |
* Allocates a new {@code Thread} object. This constructor has the same |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
472 |
* effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
473 |
* {@code (null, null, name)}. |
2 | 474 |
* |
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
475 |
* @param name |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
476 |
* the name of the new thread |
2 | 477 |
*/ |
478 |
public Thread(String name) { |
|
479 |
init(null, null, name, 0); |
|
480 |
} |
|
481 |
||
482 |
/** |
|
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
483 |
* Allocates a new {@code Thread} object. This constructor has the same |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
484 |
* effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
485 |
* {@code (group, null, name)}. |
2 | 486 |
* |
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
487 |
* @param group |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
488 |
* the thread group. If {@code null} and there is a security |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
489 |
* manager, the group is determined by {@linkplain |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
490 |
* SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}. |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
491 |
* If there is not a security manager or {@code |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
492 |
* SecurityManager.getThreadGroup()} returns {@code null}, the group |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
493 |
* is set to the current thread's thread group. |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
494 |
* |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
495 |
* @param name |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
496 |
* the name of the new thread |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
497 |
* |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
498 |
* @throws SecurityException |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
499 |
* if the current thread cannot create a thread in the specified |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
500 |
* thread group |
2 | 501 |
*/ |
502 |
public Thread(ThreadGroup group, String name) { |
|
503 |
init(group, null, name, 0); |
|
504 |
} |
|
505 |
||
506 |
/** |
|
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
507 |
* Allocates a new {@code Thread} object. This constructor has the same |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
508 |
* effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
509 |
* {@code (null, target, name)}. |
2 | 510 |
* |
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
511 |
* @param target |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
512 |
* the object whose {@code run} method is invoked when this thread |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
513 |
* is started. If {@code null}, this thread's run method is invoked. |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
514 |
* |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
515 |
* @param name |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
516 |
* the name of the new thread |
2 | 517 |
*/ |
518 |
public Thread(Runnable target, String name) { |
|
519 |
init(null, target, name, 0); |
|
520 |
} |
|
521 |
||
522 |
/** |
|
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
523 |
* Allocates a new {@code Thread} object so that it has {@code target} |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
524 |
* as its run object, has the specified {@code name} as its name, |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
525 |
* and belongs to the thread group referred to by {@code group}. |
2 | 526 |
* |
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
527 |
* <p>If there is a security manager, its |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
528 |
* {@link SecurityManager#checkAccess(ThreadGroup) checkAccess} |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
529 |
* method is invoked with the ThreadGroup as its argument. |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
530 |
* |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
531 |
* <p>In addition, its {@code checkPermission} method is invoked with |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
532 |
* the {@code RuntimePermission("enableContextClassLoaderOverride")} |
2 | 533 |
* permission when invoked directly or indirectly by the constructor |
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
534 |
* of a subclass which overrides the {@code getContextClassLoader} |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
535 |
* or {@code setContextClassLoader} methods. |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
536 |
* |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
537 |
* <p>The priority of the newly created thread is set equal to the |
2 | 538 |
* priority of the thread creating it, that is, the currently running |
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
539 |
* thread. The method {@linkplain #setPriority setPriority} may be |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
540 |
* used to change the priority to a new value. |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
541 |
* |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
542 |
* <p>The newly created thread is initially marked as being a daemon |
2 | 543 |
* thread if and only if the thread creating it is currently marked |
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
544 |
* as a daemon thread. The method {@linkplain #setDaemon setDaemon} |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
545 |
* may be used to change whether or not a thread is a daemon. |
2 | 546 |
* |
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
547 |
* @param group |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
548 |
* the thread group. If {@code null} and there is a security |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
549 |
* manager, the group is determined by {@linkplain |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
550 |
* SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}. |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
551 |
* If there is not a security manager or {@code |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
552 |
* SecurityManager.getThreadGroup()} returns {@code null}, the group |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
553 |
* is set to the current thread's thread group. |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
554 |
* |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
555 |
* @param target |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
556 |
* the object whose {@code run} method is invoked when this thread |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
557 |
* is started. If {@code null}, this thread's run method is invoked. |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
558 |
* |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
559 |
* @param name |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
560 |
* the name of the new thread |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
561 |
* |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
562 |
* @throws SecurityException |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
563 |
* if the current thread cannot create a thread in the specified |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
564 |
* thread group or cannot override the context class loader methods. |
2 | 565 |
*/ |
566 |
public Thread(ThreadGroup group, Runnable target, String name) { |
|
567 |
init(group, target, name, 0); |
|
568 |
} |
|
569 |
||
570 |
/** |
|
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
571 |
* Allocates a new {@code Thread} object so that it has {@code target} |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
572 |
* as its run object, has the specified {@code name} as its name, |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
573 |
* and belongs to the thread group referred to by {@code group}, and has |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
574 |
* the specified <i>stack size</i>. |
2 | 575 |
* |
576 |
* <p>This constructor is identical to {@link |
|
577 |
* #Thread(ThreadGroup,Runnable,String)} with the exception of the fact |
|
578 |
* that it allows the thread stack size to be specified. The stack size |
|
579 |
* is the approximate number of bytes of address space that the virtual |
|
580 |
* machine is to allocate for this thread's stack. <b>The effect of the |
|
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
581 |
* {@code stackSize} parameter, if any, is highly platform dependent.</b> |
2 | 582 |
* |
583 |
* <p>On some platforms, specifying a higher value for the |
|
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
584 |
* {@code stackSize} parameter may allow a thread to achieve greater |
2 | 585 |
* recursion depth before throwing a {@link StackOverflowError}. |
586 |
* Similarly, specifying a lower value may allow a greater number of |
|
587 |
* threads to exist concurrently without throwing an {@link |
|
588 |
* OutOfMemoryError} (or other internal error). The details of |
|
589 |
* the relationship between the value of the <tt>stackSize</tt> parameter |
|
590 |
* and the maximum recursion depth and concurrency level are |
|
591 |
* platform-dependent. <b>On some platforms, the value of the |
|
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
592 |
* {@code stackSize} parameter may have no effect whatsoever.</b> |
2 | 593 |
* |
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
594 |
* <p>The virtual machine is free to treat the {@code stackSize} |
2 | 595 |
* parameter as a suggestion. If the specified value is unreasonably low |
596 |
* for the platform, the virtual machine may instead use some |
|
597 |
* platform-specific minimum value; if the specified value is unreasonably |
|
598 |
* high, the virtual machine may instead use some platform-specific |
|
599 |
* maximum. Likewise, the virtual machine is free to round the specified |
|
600 |
* value up or down as it sees fit (or to ignore it completely). |
|
601 |
* |
|
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
602 |
* <p>Specifying a value of zero for the {@code stackSize} parameter will |
2 | 603 |
* cause this constructor to behave exactly like the |
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
604 |
* {@code Thread(ThreadGroup, Runnable, String)} constructor. |
2 | 605 |
* |
606 |
* <p><i>Due to the platform-dependent nature of the behavior of this |
|
607 |
* constructor, extreme care should be exercised in its use. |
|
608 |
* The thread stack size necessary to perform a given computation will |
|
609 |
* likely vary from one JRE implementation to another. In light of this |
|
610 |
* variation, careful tuning of the stack size parameter may be required, |
|
611 |
* and the tuning may need to be repeated for each JRE implementation on |
|
612 |
* which an application is to run.</i> |
|
613 |
* |
|
614 |
* <p>Implementation note: Java platform implementers are encouraged to |
|
615 |
* document their implementation's behavior with respect to the |
|
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
616 |
* {@code stackSize} parameter. |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
617 |
* |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
618 |
* |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
619 |
* @param group |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
620 |
* the thread group. If {@code null} and there is a security |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
621 |
* manager, the group is determined by {@linkplain |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
622 |
* SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}. |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
623 |
* If there is not a security manager or {@code |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
624 |
* SecurityManager.getThreadGroup()} returns {@code null}, the group |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
625 |
* is set to the current thread's thread group. |
2 | 626 |
* |
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
627 |
* @param target |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
628 |
* the object whose {@code run} method is invoked when this thread |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
629 |
* is started. If {@code null}, this thread's run method is invoked. |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
630 |
* |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
631 |
* @param name |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
632 |
* the name of the new thread |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
633 |
* |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
634 |
* @param stackSize |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
635 |
* the desired stack size for the new thread, or zero to indicate |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
636 |
* that this parameter is to be ignored. |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
637 |
* |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
638 |
* @throws SecurityException |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
639 |
* if the current thread cannot create a thread in the specified |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
640 |
* thread group |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
641 |
* |
2 | 642 |
* @since 1.4 |
643 |
*/ |
|
644 |
public Thread(ThreadGroup group, Runnable target, String name, |
|
645 |
long stackSize) { |
|
646 |
init(group, target, name, stackSize); |
|
647 |
} |
|
648 |
||
649 |
/** |
|
650 |
* Causes this thread to begin execution; the Java Virtual Machine |
|
651 |
* calls the <code>run</code> method of this thread. |
|
652 |
* <p> |
|
653 |
* The result is that two threads are running concurrently: the |
|
654 |
* current thread (which returns from the call to the |
|
655 |
* <code>start</code> method) and the other thread (which executes its |
|
656 |
* <code>run</code> method). |
|
657 |
* <p> |
|
658 |
* It is never legal to start a thread more than once. |
|
659 |
* In particular, a thread may not be restarted once it has completed |
|
660 |
* execution. |
|
661 |
* |
|
662 |
* @exception IllegalThreadStateException if the thread was already |
|
663 |
* started. |
|
664 |
* @see #run() |
|
665 |
* @see #stop() |
|
666 |
*/ |
|
667 |
public synchronized void start() { |
|
668 |
/** |
|
669 |
* This method is not invoked for the main method thread or "system" |
|
670 |
* group threads created/set up by the VM. Any new functionality added |
|
671 |
* to this method in the future may have to also be added to the VM. |
|
672 |
* |
|
673 |
* A zero status value corresponds to state "NEW". |
|
674 |
*/ |
|
675 |
if (threadStatus != 0) |
|
676 |
throw new IllegalThreadStateException(); |
|
677 |
||
678 |
/* Notify the group that this thread is about to be started |
|
679 |
* so that it can be added to the group's list of threads. */ |
|
680 |
group.threadStarting(this); |
|
681 |
||
682 |
boolean failed = true; |
|
683 |
try { |
|
684 |
start0(); |
|
685 |
failed = false; |
|
686 |
} finally { |
|
687 |
try { |
|
688 |
group.threadStarted(this, failed); |
|
689 |
} catch (Throwable ignore) { |
|
690 |
/* do nothing. If start0 threw a Throwable then |
|
691 |
it will be passed up the call stack */ |
|
692 |
} |
|
693 |
} |
|
694 |
||
695 |
if (stopBeforeStart) { |
|
696 |
stop0(throwableFromStop); |
|
697 |
} |
|
698 |
} |
|
699 |
||
700 |
private native void start0(); |
|
701 |
||
702 |
/** |
|
703 |
* If this thread was constructed using a separate |
|
704 |
* <code>Runnable</code> run object, then that |
|
705 |
* <code>Runnable</code> object's <code>run</code> method is called; |
|
706 |
* otherwise, this method does nothing and returns. |
|
707 |
* <p> |
|
708 |
* Subclasses of <code>Thread</code> should override this method. |
|
709 |
* |
|
710 |
* @see #start() |
|
711 |
* @see #stop() |
|
712 |
* @see #Thread(ThreadGroup, Runnable, String) |
|
713 |
*/ |
|
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
714 |
@Override |
2 | 715 |
public void run() { |
716 |
if (target != null) { |
|
717 |
target.run(); |
|
718 |
} |
|
719 |
} |
|
720 |
||
721 |
/** |
|
722 |
* This method is called by the system to give a Thread |
|
723 |
* a chance to clean up before it actually exits. |
|
724 |
*/ |
|
725 |
private void exit() { |
|
726 |
if (group != null) { |
|
727 |
group.threadTerminated(this); |
|
728 |
group = null; |
|
729 |
} |
|
730 |
/* Aggressively null out all reference fields: see bug 4006245 */ |
|
731 |
target = null; |
|
732 |
/* Speed the release of some of these resources */ |
|
733 |
threadLocals = null; |
|
734 |
inheritableThreadLocals = null; |
|
735 |
inheritedAccessControlContext = null; |
|
736 |
blocker = null; |
|
737 |
uncaughtExceptionHandler = null; |
|
738 |
} |
|
739 |
||
740 |
/** |
|
741 |
* Forces the thread to stop executing. |
|
742 |
* <p> |
|
743 |
* If there is a security manager installed, its <code>checkAccess</code> |
|
744 |
* method is called with <code>this</code> |
|
745 |
* as its argument. This may result in a |
|
746 |
* <code>SecurityException</code> being raised (in the current thread). |
|
747 |
* <p> |
|
748 |
* If this thread is different from the current thread (that is, the current |
|
749 |
* thread is trying to stop a thread other than itself), the |
|
750 |
* security manager's <code>checkPermission</code> method (with a |
|
751 |
* <code>RuntimePermission("stopThread")</code> argument) is called in |
|
752 |
* addition. |
|
753 |
* Again, this may result in throwing a |
|
754 |
* <code>SecurityException</code> (in the current thread). |
|
755 |
* <p> |
|
756 |
* The thread represented by this thread is forced to stop whatever |
|
757 |
* it is doing abnormally and to throw a newly created |
|
758 |
* <code>ThreadDeath</code> object as an exception. |
|
759 |
* <p> |
|
760 |
* It is permitted to stop a thread that has not yet been started. |
|
761 |
* If the thread is eventually started, it immediately terminates. |
|
762 |
* <p> |
|
763 |
* An application should not normally try to catch |
|
764 |
* <code>ThreadDeath</code> unless it must do some extraordinary |
|
765 |
* cleanup operation (note that the throwing of |
|
766 |
* <code>ThreadDeath</code> causes <code>finally</code> clauses of |
|
767 |
* <code>try</code> statements to be executed before the thread |
|
768 |
* officially dies). If a <code>catch</code> clause catches a |
|
769 |
* <code>ThreadDeath</code> object, it is important to rethrow the |
|
770 |
* object so that the thread actually dies. |
|
771 |
* <p> |
|
772 |
* The top-level error handler that reacts to otherwise uncaught |
|
773 |
* exceptions does not print out a message or otherwise notify the |
|
774 |
* application if the uncaught exception is an instance of |
|
775 |
* <code>ThreadDeath</code>. |
|
776 |
* |
|
777 |
* @exception SecurityException if the current thread cannot |
|
778 |
* modify this thread. |
|
779 |
* @see #interrupt() |
|
780 |
* @see #checkAccess() |
|
781 |
* @see #run() |
|
782 |
* @see #start() |
|
783 |
* @see ThreadDeath |
|
784 |
* @see ThreadGroup#uncaughtException(Thread,Throwable) |
|
785 |
* @see SecurityManager#checkAccess(Thread) |
|
786 |
* @see SecurityManager#checkPermission |
|
787 |
* @deprecated This method is inherently unsafe. Stopping a thread with |
|
788 |
* Thread.stop causes it to unlock all of the monitors that it |
|
789 |
* has locked (as a natural consequence of the unchecked |
|
790 |
* <code>ThreadDeath</code> exception propagating up the stack). If |
|
791 |
* any of the objects previously protected by these monitors were in |
|
792 |
* an inconsistent state, the damaged objects become visible to |
|
793 |
* other threads, potentially resulting in arbitrary behavior. Many |
|
794 |
* uses of <code>stop</code> should be replaced by code that simply |
|
795 |
* modifies some variable to indicate that the target thread should |
|
796 |
* stop running. The target thread should check this variable |
|
797 |
* regularly, and return from its run method in an orderly fashion |
|
798 |
* if the variable indicates that it is to stop running. If the |
|
799 |
* target thread waits for long periods (on a condition variable, |
|
800 |
* for example), the <code>interrupt</code> method should be used to |
|
801 |
* interrupt the wait. |
|
802 |
* For more information, see |
|
803 |
* <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why |
|
804 |
* are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>. |
|
805 |
*/ |
|
806 |
@Deprecated |
|
807 |
public final void stop() { |
|
808 |
// If the thread is already dead, return. |
|
809 |
// A zero status value corresponds to "NEW". |
|
810 |
if ((threadStatus != 0) && !isAlive()) { |
|
811 |
return; |
|
812 |
} |
|
813 |
stop1(new ThreadDeath()); |
|
814 |
} |
|
815 |
||
816 |
/** |
|
817 |
* Forces the thread to stop executing. |
|
818 |
* <p> |
|
819 |
* If there is a security manager installed, the <code>checkAccess</code> |
|
820 |
* method of this thread is called, which may result in a |
|
821 |
* <code>SecurityException</code> being raised (in the current thread). |
|
822 |
* <p> |
|
823 |
* If this thread is different from the current thread (that is, the current |
|
824 |
* thread is trying to stop a thread other than itself) or |
|
825 |
* <code>obj</code> is not an instance of <code>ThreadDeath</code>, the |
|
826 |
* security manager's <code>checkPermission</code> method (with the |
|
827 |
* <code>RuntimePermission("stopThread")</code> argument) is called in |
|
828 |
* addition. |
|
829 |
* Again, this may result in throwing a |
|
830 |
* <code>SecurityException</code> (in the current thread). |
|
831 |
* <p> |
|
832 |
* If the argument <code>obj</code> is null, a |
|
833 |
* <code>NullPointerException</code> is thrown (in the current thread). |
|
834 |
* <p> |
|
835 |
* The thread represented by this thread is forced to stop |
|
836 |
* whatever it is doing abnormally and to throw the |
|
837 |
* <code>Throwable</code> object <code>obj</code> as an exception. This |
|
838 |
* is an unusual action to take; normally, the <code>stop</code> method |
|
839 |
* that takes no arguments should be used. |
|
840 |
* <p> |
|
841 |
* It is permitted to stop a thread that has not yet been started. |
|
842 |
* If the thread is eventually started, it immediately terminates. |
|
843 |
* |
|
844 |
* @param obj the Throwable object to be thrown. |
|
845 |
* @exception SecurityException if the current thread cannot modify |
|
846 |
* this thread. |
|
847 |
* @throws NullPointerException if obj is <tt>null</tt>. |
|
848 |
* @see #interrupt() |
|
849 |
* @see #checkAccess() |
|
850 |
* @see #run() |
|
851 |
* @see #start() |
|
852 |
* @see #stop() |
|
853 |
* @see SecurityManager#checkAccess(Thread) |
|
854 |
* @see SecurityManager#checkPermission |
|
855 |
* @deprecated This method is inherently unsafe. See {@link #stop()} |
|
856 |
* for details. An additional danger of this |
|
857 |
* method is that it may be used to generate exceptions that the |
|
858 |
* target thread is unprepared to handle (including checked |
|
859 |
* exceptions that the thread could not possibly throw, were it |
|
860 |
* not for this method). |
|
861 |
* For more information, see |
|
862 |
* <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why |
|
863 |
* are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>. |
|
864 |
*/ |
|
865 |
@Deprecated |
|
866 |
public final synchronized void stop(Throwable obj) { |
|
867 |
stop1(obj); |
|
868 |
} |
|
869 |
||
870 |
/** |
|
871 |
* Common impl for stop() and stop(Throwable). |
|
872 |
*/ |
|
873 |
private final synchronized void stop1(Throwable th) { |
|
874 |
SecurityManager security = System.getSecurityManager(); |
|
875 |
if (security != null) { |
|
876 |
checkAccess(); |
|
877 |
if ((this != Thread.currentThread()) || |
|
878 |
(!(th instanceof ThreadDeath))) { |
|
879 |
security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION); |
|
880 |
} |
|
881 |
} |
|
882 |
// A zero status value corresponds to "NEW" |
|
883 |
if (threadStatus != 0) { |
|
884 |
resume(); // Wake up thread if it was suspended; no-op otherwise |
|
885 |
stop0(th); |
|
886 |
} else { |
|
887 |
||
888 |
// Must do the null arg check that the VM would do with stop0 |
|
889 |
if (th == null) { |
|
890 |
throw new NullPointerException(); |
|
891 |
} |
|
892 |
||
893 |
// Remember this stop attempt for if/when start is used |
|
894 |
stopBeforeStart = true; |
|
895 |
throwableFromStop = th; |
|
896 |
} |
|
897 |
} |
|
898 |
||
899 |
/** |
|
900 |
* Interrupts this thread. |
|
901 |
* |
|
902 |
* <p> Unless the current thread is interrupting itself, which is |
|
903 |
* always permitted, the {@link #checkAccess() checkAccess} method |
|
904 |
* of this thread is invoked, which may cause a {@link |
|
905 |
* SecurityException} to be thrown. |
|
906 |
* |
|
907 |
* <p> If this thread is blocked in an invocation of the {@link |
|
908 |
* Object#wait() wait()}, {@link Object#wait(long) wait(long)}, or {@link |
|
909 |
* Object#wait(long, int) wait(long, int)} methods of the {@link Object} |
|
910 |
* class, or of the {@link #join()}, {@link #join(long)}, {@link |
|
911 |
* #join(long, int)}, {@link #sleep(long)}, or {@link #sleep(long, int)}, |
|
912 |
* methods of this class, then its interrupt status will be cleared and it |
|
913 |
* will receive an {@link InterruptedException}. |
|
914 |
* |
|
915 |
* <p> If this thread is blocked in an I/O operation upon an {@link |
|
916 |
* java.nio.channels.InterruptibleChannel </code>interruptible |
|
917 |
* channel<code>} then the channel will be closed, the thread's interrupt |
|
918 |
* status will be set, and the thread will receive a {@link |
|
919 |
* java.nio.channels.ClosedByInterruptException}. |
|
920 |
* |
|
921 |
* <p> If this thread is blocked in a {@link java.nio.channels.Selector} |
|
922 |
* then the thread's interrupt status will be set and it will return |
|
923 |
* immediately from the selection operation, possibly with a non-zero |
|
924 |
* value, just as if the selector's {@link |
|
925 |
* java.nio.channels.Selector#wakeup wakeup} method were invoked. |
|
926 |
* |
|
927 |
* <p> If none of the previous conditions hold then this thread's interrupt |
|
928 |
* status will be set. </p> |
|
929 |
* |
|
930 |
* <p> Interrupting a thread that is not alive need not have any effect. |
|
931 |
* |
|
932 |
* @throws SecurityException |
|
933 |
* if the current thread cannot modify this thread |
|
934 |
* |
|
935 |
* @revised 6.0 |
|
936 |
* @spec JSR-51 |
|
937 |
*/ |
|
938 |
public void interrupt() { |
|
939 |
if (this != Thread.currentThread()) |
|
940 |
checkAccess(); |
|
941 |
||
942 |
synchronized (blockerLock) { |
|
943 |
Interruptible b = blocker; |
|
944 |
if (b != null) { |
|
945 |
interrupt0(); // Just to set the interrupt flag |
|
946 |
b.interrupt(); |
|
947 |
return; |
|
948 |
} |
|
949 |
} |
|
950 |
interrupt0(); |
|
951 |
} |
|
952 |
||
953 |
/** |
|
954 |
* Tests whether the current thread has been interrupted. The |
|
955 |
* <i>interrupted status</i> of the thread is cleared by this method. In |
|
956 |
* other words, if this method were to be called twice in succession, the |
|
957 |
* second call would return false (unless the current thread were |
|
958 |
* interrupted again, after the first call had cleared its interrupted |
|
959 |
* status and before the second call had examined it). |
|
960 |
* |
|
961 |
* <p>A thread interruption ignored because a thread was not alive |
|
962 |
* at the time of the interrupt will be reflected by this method |
|
963 |
* returning false. |
|
964 |
* |
|
965 |
* @return <code>true</code> if the current thread has been interrupted; |
|
966 |
* <code>false</code> otherwise. |
|
967 |
* @see #isInterrupted() |
|
968 |
* @revised 6.0 |
|
969 |
*/ |
|
970 |
public static boolean interrupted() { |
|
971 |
return currentThread().isInterrupted(true); |
|
972 |
} |
|
973 |
||
974 |
/** |
|
975 |
* Tests whether this thread has been interrupted. The <i>interrupted |
|
976 |
* status</i> of the thread is unaffected by this method. |
|
977 |
* |
|
978 |
* <p>A thread interruption ignored because a thread was not alive |
|
979 |
* at the time of the interrupt will be reflected by this method |
|
980 |
* returning false. |
|
981 |
* |
|
982 |
* @return <code>true</code> if this thread has been interrupted; |
|
983 |
* <code>false</code> otherwise. |
|
984 |
* @see #interrupted() |
|
985 |
* @revised 6.0 |
|
986 |
*/ |
|
987 |
public boolean isInterrupted() { |
|
988 |
return isInterrupted(false); |
|
989 |
} |
|
990 |
||
991 |
/** |
|
992 |
* Tests if some Thread has been interrupted. The interrupted state |
|
993 |
* is reset or not based on the value of ClearInterrupted that is |
|
994 |
* passed. |
|
995 |
*/ |
|
996 |
private native boolean isInterrupted(boolean ClearInterrupted); |
|
997 |
||
998 |
/** |
|
999 |
* Throws {@link NoSuchMethodError}. |
|
1000 |
* |
|
1001 |
* @deprecated This method was originally designed to destroy this |
|
1002 |
* thread without any cleanup. Any monitors it held would have |
|
1003 |
* remained locked. However, the method was never implemented. |
|
1004 |
* If if were to be implemented, it would be deadlock-prone in |
|
1005 |
* much the manner of {@link #suspend}. If the target thread held |
|
1006 |
* a lock protecting a critical system resource when it was |
|
1007 |
* destroyed, no thread could ever access this resource again. |
|
1008 |
* If another thread ever attempted to lock this resource, deadlock |
|
1009 |
* would result. Such deadlocks typically manifest themselves as |
|
1010 |
* "frozen" processes. For more information, see |
|
1011 |
* <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html"> |
|
1012 |
* Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>. |
|
1013 |
* @throws NoSuchMethodError always |
|
1014 |
*/ |
|
1015 |
@Deprecated |
|
1016 |
public void destroy() { |
|
1017 |
throw new NoSuchMethodError(); |
|
1018 |
} |
|
1019 |
||
1020 |
/** |
|
1021 |
* Tests if this thread is alive. A thread is alive if it has |
|
1022 |
* been started and has not yet died. |
|
1023 |
* |
|
1024 |
* @return <code>true</code> if this thread is alive; |
|
1025 |
* <code>false</code> otherwise. |
|
1026 |
*/ |
|
1027 |
public final native boolean isAlive(); |
|
1028 |
||
1029 |
/** |
|
1030 |
* Suspends this thread. |
|
1031 |
* <p> |
|
1032 |
* First, the <code>checkAccess</code> method of this thread is called |
|
1033 |
* with no arguments. This may result in throwing a |
|
1034 |
* <code>SecurityException </code>(in the current thread). |
|
1035 |
* <p> |
|
1036 |
* If the thread is alive, it is suspended and makes no further |
|
1037 |
* progress unless and until it is resumed. |
|
1038 |
* |
|
1039 |
* @exception SecurityException if the current thread cannot modify |
|
1040 |
* this thread. |
|
1041 |
* @see #checkAccess |
|
1042 |
* @deprecated This method has been deprecated, as it is |
|
1043 |
* inherently deadlock-prone. If the target thread holds a lock on the |
|
1044 |
* monitor protecting a critical system resource when it is suspended, no |
|
1045 |
* thread can access this resource until the target thread is resumed. If |
|
1046 |
* the thread that would resume the target thread attempts to lock this |
|
1047 |
* monitor prior to calling <code>resume</code>, deadlock results. Such |
|
1048 |
* deadlocks typically manifest themselves as "frozen" processes. |
|
1049 |
* For more information, see |
|
1050 |
* <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why |
|
1051 |
* are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>. |
|
1052 |
*/ |
|
1053 |
@Deprecated |
|
1054 |
public final void suspend() { |
|
1055 |
checkAccess(); |
|
1056 |
suspend0(); |
|
1057 |
} |
|
1058 |
||
1059 |
/** |
|
1060 |
* Resumes a suspended thread. |
|
1061 |
* <p> |
|
1062 |
* First, the <code>checkAccess</code> method of this thread is called |
|
1063 |
* with no arguments. This may result in throwing a |
|
1064 |
* <code>SecurityException</code> (in the current thread). |
|
1065 |
* <p> |
|
1066 |
* If the thread is alive but suspended, it is resumed and is |
|
1067 |
* permitted to make progress in its execution. |
|
1068 |
* |
|
1069 |
* @exception SecurityException if the current thread cannot modify this |
|
1070 |
* thread. |
|
1071 |
* @see #checkAccess |
|
1072 |
* @see #suspend() |
|
1073 |
* @deprecated This method exists solely for use with {@link #suspend}, |
|
1074 |
* which has been deprecated because it is deadlock-prone. |
|
1075 |
* For more information, see |
|
1076 |
* <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why |
|
1077 |
* are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>. |
|
1078 |
*/ |
|
1079 |
@Deprecated |
|
1080 |
public final void resume() { |
|
1081 |
checkAccess(); |
|
1082 |
resume0(); |
|
1083 |
} |
|
1084 |
||
1085 |
/** |
|
1086 |
* Changes the priority of this thread. |
|
1087 |
* <p> |
|
1088 |
* First the <code>checkAccess</code> method of this thread is called |
|
1089 |
* with no arguments. This may result in throwing a |
|
1090 |
* <code>SecurityException</code>. |
|
1091 |
* <p> |
|
1092 |
* Otherwise, the priority of this thread is set to the smaller of |
|
1093 |
* the specified <code>newPriority</code> and the maximum permitted |
|
1094 |
* priority of the thread's thread group. |
|
1095 |
* |
|
1096 |
* @param newPriority priority to set this thread to |
|
1097 |
* @exception IllegalArgumentException If the priority is not in the |
|
1098 |
* range <code>MIN_PRIORITY</code> to |
|
1099 |
* <code>MAX_PRIORITY</code>. |
|
1100 |
* @exception SecurityException if the current thread cannot modify |
|
1101 |
* this thread. |
|
1102 |
* @see #getPriority |
|
1103 |
* @see #checkAccess() |
|
1104 |
* @see #getThreadGroup() |
|
1105 |
* @see #MAX_PRIORITY |
|
1106 |
* @see #MIN_PRIORITY |
|
1107 |
* @see ThreadGroup#getMaxPriority() |
|
1108 |
*/ |
|
1109 |
public final void setPriority(int newPriority) { |
|
1110 |
ThreadGroup g; |
|
1111 |
checkAccess(); |
|
1112 |
if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) { |
|
1113 |
throw new IllegalArgumentException(); |
|
1114 |
} |
|
1115 |
if((g = getThreadGroup()) != null) { |
|
1116 |
if (newPriority > g.getMaxPriority()) { |
|
1117 |
newPriority = g.getMaxPriority(); |
|
1118 |
} |
|
1119 |
setPriority0(priority = newPriority); |
|
1120 |
} |
|
1121 |
} |
|
1122 |
||
1123 |
/** |
|
1124 |
* Returns this thread's priority. |
|
1125 |
* |
|
1126 |
* @return this thread's priority. |
|
1127 |
* @see #setPriority |
|
1128 |
*/ |
|
1129 |
public final int getPriority() { |
|
1130 |
return priority; |
|
1131 |
} |
|
1132 |
||
1133 |
/** |
|
1134 |
* Changes the name of this thread to be equal to the argument |
|
1135 |
* <code>name</code>. |
|
1136 |
* <p> |
|
1137 |
* First the <code>checkAccess</code> method of this thread is called |
|
1138 |
* with no arguments. This may result in throwing a |
|
1139 |
* <code>SecurityException</code>. |
|
1140 |
* |
|
1141 |
* @param name the new name for this thread. |
|
1142 |
* @exception SecurityException if the current thread cannot modify this |
|
1143 |
* thread. |
|
1144 |
* @see #getName |
|
1145 |
* @see #checkAccess() |
|
1146 |
*/ |
|
1147 |
public final void setName(String name) { |
|
1148 |
checkAccess(); |
|
1149 |
this.name = name.toCharArray(); |
|
1150 |
} |
|
1151 |
||
1152 |
/** |
|
1153 |
* Returns this thread's name. |
|
1154 |
* |
|
1155 |
* @return this thread's name. |
|
1156 |
* @see #setName(String) |
|
1157 |
*/ |
|
1158 |
public final String getName() { |
|
1159 |
return String.valueOf(name); |
|
1160 |
} |
|
1161 |
||
1162 |
/** |
|
1163 |
* Returns the thread group to which this thread belongs. |
|
1164 |
* This method returns null if this thread has died |
|
1165 |
* (been stopped). |
|
1166 |
* |
|
1167 |
* @return this thread's thread group. |
|
1168 |
*/ |
|
1169 |
public final ThreadGroup getThreadGroup() { |
|
1170 |
return group; |
|
1171 |
} |
|
1172 |
||
1173 |
/** |
|
1174 |
* Returns an estimate of the number of active threads in the current |
|
1175 |
* thread's {@linkplain java.lang.ThreadGroup thread group} and its |
|
1176 |
* subgroups. Recursively iterates over all subgroups in the current |
|
1177 |
* thread's thread group. |
|
1178 |
* |
|
1179 |
* <p> The value returned is only an estimate because the number of |
|
1180 |
* threads may change dynamically while this method traverses internal |
|
1181 |
* data structures, and might be affected by the presence of certain |
|
1182 |
* system threads. This method is intended primarily for debugging |
|
1183 |
* and monitoring purposes. |
|
1184 |
* |
|
1185 |
* @return an estimate of the number of active threads in the current |
|
1186 |
* thread's thread group and in any other thread group that |
|
1187 |
* has the current thread's thread group as an ancestor |
|
1188 |
*/ |
|
1189 |
public static int activeCount() { |
|
1190 |
return currentThread().getThreadGroup().activeCount(); |
|
1191 |
} |
|
1192 |
||
1193 |
/** |
|
1194 |
* Copies into the specified array every active thread in the current |
|
1195 |
* thread's thread group and its subgroups. This method simply |
|
1196 |
* invokes the {@link java.lang.ThreadGroup#enumerate(Thread[])} |
|
1197 |
* method of the current thread's thread group. |
|
1198 |
* |
|
1199 |
* <p> An application might use the {@linkplain #activeCount activeCount} |
|
1200 |
* method to get an estimate of how big the array should be, however |
|
1201 |
* <i>if the array is too short to hold all the threads, the extra threads |
|
1202 |
* are silently ignored.</i> If it is critical to obtain every active |
|
1203 |
* thread in the current thread's thread group and its subgroups, the |
|
1204 |
* invoker should verify that the returned int value is strictly less |
|
1205 |
* than the length of {@code tarray}. |
|
1206 |
* |
|
1207 |
* <p> Due to the inherent race condition in this method, it is recommended |
|
1208 |
* that the method only be used for debugging and monitoring purposes. |
|
1209 |
* |
|
1210 |
* @param tarray |
|
1211 |
* an array into which to put the list of threads |
|
1212 |
* |
|
1213 |
* @return the number of threads put into the array |
|
1214 |
* |
|
1215 |
* @throws SecurityException |
|
1216 |
* if {@link java.lang.ThreadGroup#checkAccess} determines that |
|
1217 |
* the current thread cannot access its thread group |
|
1218 |
*/ |
|
1219 |
public static int enumerate(Thread tarray[]) { |
|
1220 |
return currentThread().getThreadGroup().enumerate(tarray); |
|
1221 |
} |
|
1222 |
||
1223 |
/** |
|
1224 |
* Counts the number of stack frames in this thread. The thread must |
|
1225 |
* be suspended. |
|
1226 |
* |
|
1227 |
* @return the number of stack frames in this thread. |
|
1228 |
* @exception IllegalThreadStateException if this thread is not |
|
1229 |
* suspended. |
|
1230 |
* @deprecated The definition of this call depends on {@link #suspend}, |
|
1231 |
* which is deprecated. Further, the results of this call |
|
1232 |
* were never well-defined. |
|
1233 |
*/ |
|
1234 |
@Deprecated |
|
1235 |
public native int countStackFrames(); |
|
1236 |
||
1237 |
/** |
|
1238 |
* Waits at most {@code millis} milliseconds for this thread to |
|
1239 |
* die. A timeout of {@code 0} means to wait forever. |
|
1240 |
* |
|
1241 |
* <p> This implementation uses a loop of {@code this.wait} calls |
|
1242 |
* conditioned on {@code this.isAlive}. As a thread terminates the |
|
1243 |
* {@code this.notifyAll} method is invoked. It is recommended that |
|
1244 |
* applications not use {@code wait}, {@code notify}, or |
|
1245 |
* {@code notifyAll} on {@code Thread} instances. |
|
1246 |
* |
|
1247 |
* @param millis |
|
1248 |
* the time to wait in milliseconds |
|
1249 |
* |
|
1250 |
* @throws IllegalArgumentException |
|
1251 |
* if the value of {@code millis} is negative |
|
1252 |
* |
|
1253 |
* @throws InterruptedException |
|
1254 |
* if any thread has interrupted the current thread. The |
|
1255 |
* <i>interrupted status</i> of the current thread is |
|
1256 |
* cleared when this exception is thrown. |
|
1257 |
*/ |
|
1258 |
public final synchronized void join(long millis) |
|
1259 |
throws InterruptedException { |
|
1260 |
long base = System.currentTimeMillis(); |
|
1261 |
long now = 0; |
|
1262 |
||
1263 |
if (millis < 0) { |
|
1264 |
throw new IllegalArgumentException("timeout value is negative"); |
|
1265 |
} |
|
1266 |
||
1267 |
if (millis == 0) { |
|
1268 |
while (isAlive()) { |
|
1269 |
wait(0); |
|
1270 |
} |
|
1271 |
} else { |
|
1272 |
while (isAlive()) { |
|
1273 |
long delay = millis - now; |
|
1274 |
if (delay <= 0) { |
|
1275 |
break; |
|
1276 |
} |
|
1277 |
wait(delay); |
|
1278 |
now = System.currentTimeMillis() - base; |
|
1279 |
} |
|
1280 |
} |
|
1281 |
} |
|
1282 |
||
1283 |
/** |
|
1284 |
* Waits at most {@code millis} milliseconds plus |
|
1285 |
* {@code nanos} nanoseconds for this thread to die. |
|
1286 |
* |
|
1287 |
* <p> This implementation uses a loop of {@code this.wait} calls |
|
1288 |
* conditioned on {@code this.isAlive}. As a thread terminates the |
|
1289 |
* {@code this.notifyAll} method is invoked. It is recommended that |
|
1290 |
* applications not use {@code wait}, {@code notify}, or |
|
1291 |
* {@code notifyAll} on {@code Thread} instances. |
|
1292 |
* |
|
1293 |
* @param millis |
|
1294 |
* the time to wait in milliseconds |
|
1295 |
* |
|
1296 |
* @param nanos |
|
1297 |
* {@code 0-999999} additional nanoseconds to wait |
|
1298 |
* |
|
1299 |
* @throws IllegalArgumentException |
|
1300 |
* if the value of {@code millis} is negative, or the value |
|
1301 |
* of {@code nanos} is not in the range {@code 0-999999} |
|
1302 |
* |
|
1303 |
* @throws InterruptedException |
|
1304 |
* if any thread has interrupted the current thread. The |
|
1305 |
* <i>interrupted status</i> of the current thread is |
|
1306 |
* cleared when this exception is thrown. |
|
1307 |
*/ |
|
1308 |
public final synchronized void join(long millis, int nanos) |
|
1309 |
throws InterruptedException { |
|
1310 |
||
1311 |
if (millis < 0) { |
|
1312 |
throw new IllegalArgumentException("timeout value is negative"); |
|
1313 |
} |
|
1314 |
||
1315 |
if (nanos < 0 || nanos > 999999) { |
|
1316 |
throw new IllegalArgumentException( |
|
1317 |
"nanosecond timeout value out of range"); |
|
1318 |
} |
|
1319 |
||
1320 |
if (nanos >= 500000 || (nanos != 0 && millis == 0)) { |
|
1321 |
millis++; |
|
1322 |
} |
|
1323 |
||
1324 |
join(millis); |
|
1325 |
} |
|
1326 |
||
1327 |
/** |
|
1328 |
* Waits for this thread to die. |
|
1329 |
* |
|
1330 |
* <p> An invocation of this method behaves in exactly the same |
|
1331 |
* way as the invocation |
|
1332 |
* |
|
1333 |
* <blockquote> |
|
1334 |
* {@linkplain #join(long) join}{@code (0)} |
|
1335 |
* </blockquote> |
|
1336 |
* |
|
1337 |
* @throws InterruptedException |
|
1338 |
* if any thread has interrupted the current thread. The |
|
1339 |
* <i>interrupted status</i> of the current thread is |
|
1340 |
* cleared when this exception is thrown. |
|
1341 |
*/ |
|
1342 |
public final void join() throws InterruptedException { |
|
1343 |
join(0); |
|
1344 |
} |
|
1345 |
||
1346 |
/** |
|
1347 |
* Prints a stack trace of the current thread to the standard error stream. |
|
1348 |
* This method is used only for debugging. |
|
1349 |
* |
|
1350 |
* @see Throwable#printStackTrace() |
|
1351 |
*/ |
|
1352 |
public static void dumpStack() { |
|
1353 |
new Exception("Stack trace").printStackTrace(); |
|
1354 |
} |
|
1355 |
||
1356 |
/** |
|
1357 |
* Marks this thread as either a {@linkplain #isDaemon daemon} thread |
|
1358 |
* or a user thread. The Java Virtual Machine exits when the only |
|
1359 |
* threads running are all daemon threads. |
|
1360 |
* |
|
1361 |
* <p> This method must be invoked before the thread is started. |
|
1362 |
* |
|
1363 |
* @param on |
|
1364 |
* if {@code true}, marks this thread as a daemon thread |
|
1365 |
* |
|
1366 |
* @throws IllegalThreadStateException |
|
1367 |
* if this thread is {@linkplain #isAlive alive} |
|
1368 |
* |
|
1369 |
* @throws SecurityException |
|
1370 |
* if {@link #checkAccess} determines that the current |
|
1371 |
* thread cannot modify this thread |
|
1372 |
*/ |
|
1373 |
public final void setDaemon(boolean on) { |
|
1374 |
checkAccess(); |
|
1375 |
if (isAlive()) { |
|
1376 |
throw new IllegalThreadStateException(); |
|
1377 |
} |
|
1378 |
daemon = on; |
|
1379 |
} |
|
1380 |
||
1381 |
/** |
|
1382 |
* Tests if this thread is a daemon thread. |
|
1383 |
* |
|
1384 |
* @return <code>true</code> if this thread is a daemon thread; |
|
1385 |
* <code>false</code> otherwise. |
|
1386 |
* @see #setDaemon(boolean) |
|
1387 |
*/ |
|
1388 |
public final boolean isDaemon() { |
|
1389 |
return daemon; |
|
1390 |
} |
|
1391 |
||
1392 |
/** |
|
1393 |
* Determines if the currently running thread has permission to |
|
1394 |
* modify this thread. |
|
1395 |
* <p> |
|
1396 |
* If there is a security manager, its <code>checkAccess</code> method |
|
1397 |
* is called with this thread as its argument. This may result in |
|
1398 |
* throwing a <code>SecurityException</code>. |
|
1399 |
* |
|
1400 |
* @exception SecurityException if the current thread is not allowed to |
|
1401 |
* access this thread. |
|
1402 |
* @see SecurityManager#checkAccess(Thread) |
|
1403 |
*/ |
|
1404 |
public final void checkAccess() { |
|
1405 |
SecurityManager security = System.getSecurityManager(); |
|
1406 |
if (security != null) { |
|
1407 |
security.checkAccess(this); |
|
1408 |
} |
|
1409 |
} |
|
1410 |
||
1411 |
/** |
|
1412 |
* Returns a string representation of this thread, including the |
|
1413 |
* thread's name, priority, and thread group. |
|
1414 |
* |
|
1415 |
* @return a string representation of this thread. |
|
1416 |
*/ |
|
1417 |
public String toString() { |
|
1418 |
ThreadGroup group = getThreadGroup(); |
|
1419 |
if (group != null) { |
|
1420 |
return "Thread[" + getName() + "," + getPriority() + "," + |
|
1421 |
group.getName() + "]"; |
|
1422 |
} else { |
|
1423 |
return "Thread[" + getName() + "," + getPriority() + "," + |
|
1424 |
"" + "]"; |
|
1425 |
} |
|
1426 |
} |
|
1427 |
||
1428 |
/** |
|
1429 |
* Returns the context ClassLoader for this Thread. The context |
|
1430 |
* ClassLoader is provided by the creator of the thread for use |
|
1431 |
* by code running in this thread when loading classes and resources. |
|
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1432 |
* If not {@linkplain #setContextClassLoader set}, the default is the |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1433 |
* ClassLoader context of the parent Thread. The context ClassLoader of the |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1434 |
* primordial thread is typically set to the class loader used to load the |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1435 |
* application. |
2 | 1436 |
* |
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1437 |
* <p>If a security manager is present, and the invoker's class loader is not |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1438 |
* {@code null} and is not the same as or an ancestor of the context class |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1439 |
* loader, then this method invokes the security manager's {@link |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1440 |
* SecurityManager#checkPermission(java.security.Permission) checkPermission} |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1441 |
* method with a {@link RuntimePermission RuntimePermission}{@code |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1442 |
* ("getClassLoader")} permission to verify that retrieval of the context |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1443 |
* class loader is permitted. |
2 | 1444 |
* |
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1445 |
* @return the context ClassLoader for this Thread, or {@code null} |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1446 |
* indicating the system class loader (or, failing that, the |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1447 |
* bootstrap class loader) |
2 | 1448 |
* |
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1449 |
* @throws SecurityException |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1450 |
* if the current thread cannot get the context ClassLoader |
2 | 1451 |
* |
1452 |
* @since 1.2 |
|
1453 |
*/ |
|
1454 |
public ClassLoader getContextClassLoader() { |
|
1455 |
if (contextClassLoader == null) |
|
1456 |
return null; |
|
1457 |
SecurityManager sm = System.getSecurityManager(); |
|
1458 |
if (sm != null) { |
|
1459 |
ClassLoader ccl = ClassLoader.getCallerClassLoader(); |
|
1460 |
if (ccl != null && ccl != contextClassLoader && |
|
1461 |
!contextClassLoader.isAncestor(ccl)) { |
|
1462 |
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); |
|
1463 |
} |
|
1464 |
} |
|
1465 |
return contextClassLoader; |
|
1466 |
} |
|
1467 |
||
1468 |
/** |
|
1469 |
* Sets the context ClassLoader for this Thread. The context |
|
1470 |
* ClassLoader can be set when a thread is created, and allows |
|
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1471 |
* the creator of the thread to provide the appropriate class loader, |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1472 |
* through {@code getContextClassLoader}, to code running in the thread |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1473 |
* when loading classes and resources. |
2 | 1474 |
* |
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1475 |
* <p>If a security manager is present, its {@link |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1476 |
* SecurityManager#checkPermission(java.security.Permission) checkPermission} |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1477 |
* method is invoked with a {@link RuntimePermission RuntimePermission}{@code |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1478 |
* ("setContextClassLoader")} permission to see if setting the context |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1479 |
* ClassLoader is permitted. |
2 | 1480 |
* |
1148
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1481 |
* @param cl |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1482 |
* the context ClassLoader for this Thread, or null indicating the |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1483 |
* system class loader (or, failing that, the bootstrap class loader) |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1484 |
* |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1485 |
* @throws SecurityException |
1e917f49e503
6576763: Thread constructors throw undocumented NPE for null name
chegar
parents:
2
diff
changeset
|
1486 |
* if the current thread cannot set the context ClassLoader |
2 | 1487 |
* |
1488 |
* @since 1.2 |
|
1489 |
*/ |
|
1490 |
public void setContextClassLoader(ClassLoader cl) { |
|
1491 |
SecurityManager sm = System.getSecurityManager(); |
|
1492 |
if (sm != null) { |
|
1493 |
sm.checkPermission(new RuntimePermission("setContextClassLoader")); |
|
1494 |
} |
|
1495 |
contextClassLoader = cl; |
|
1496 |
} |
|
1497 |
||
1498 |
/** |
|
1499 |
* Returns <tt>true</tt> if and only if the current thread holds the |
|
1500 |
* monitor lock on the specified object. |
|
1501 |
* |
|
1502 |
* <p>This method is designed to allow a program to assert that |
|
1503 |
* the current thread already holds a specified lock: |
|
1504 |
* <pre> |
|
1505 |
* assert Thread.holdsLock(obj); |
|
1506 |
* </pre> |
|
1507 |
* |
|
1508 |
* @param obj the object on which to test lock ownership |
|
1509 |
* @throws NullPointerException if obj is <tt>null</tt> |
|
1510 |
* @return <tt>true</tt> if the current thread holds the monitor lock on |
|
1511 |
* the specified object. |
|
1512 |
* @since 1.4 |
|
1513 |
*/ |
|
1514 |
public static native boolean holdsLock(Object obj); |
|
1515 |
||
1516 |
private static final StackTraceElement[] EMPTY_STACK_TRACE |
|
1517 |
= new StackTraceElement[0]; |
|
1518 |
||
1519 |
/** |
|
1520 |
* Returns an array of stack trace elements representing the stack dump |
|
1521 |
* of this thread. This method will return a zero-length array if |
|
1522 |
* this thread has not started, has started but has not yet been |
|
1523 |
* scheduled to run by the system, or has terminated. |
|
1524 |
* If the returned array is of non-zero length then the first element of |
|
1525 |
* the array represents the top of the stack, which is the most recent |
|
1526 |
* method invocation in the sequence. The last element of the array |
|
1527 |
* represents the bottom of the stack, which is the least recent method |
|
1528 |
* invocation in the sequence. |
|
1529 |
* |
|
1530 |
* <p>If there is a security manager, and this thread is not |
|
1531 |
* the current thread, then the security manager's |
|
1532 |
* <tt>checkPermission</tt> method is called with a |
|
1533 |
* <tt>RuntimePermission("getStackTrace")</tt> permission |
|
1534 |
* to see if it's ok to get the stack trace. |
|
1535 |
* |
|
1536 |
* <p>Some virtual machines may, under some circumstances, omit one |
|
1537 |
* or more stack frames from the stack trace. In the extreme case, |
|
1538 |
* a virtual machine that has no stack trace information concerning |
|
1539 |
* this thread is permitted to return a zero-length array from this |
|
1540 |
* method. |
|
1541 |
* |
|
1542 |
* @return an array of <tt>StackTraceElement</tt>, |
|
1543 |
* each represents one stack frame. |
|
1544 |
* |
|
1545 |
* @throws SecurityException |
|
1546 |
* if a security manager exists and its |
|
1547 |
* <tt>checkPermission</tt> method doesn't allow |
|
1548 |
* getting the stack trace of thread. |
|
1549 |
* @see SecurityManager#checkPermission |
|
1550 |
* @see RuntimePermission |
|
1551 |
* @see Throwable#getStackTrace |
|
1552 |
* |
|
1553 |
* @since 1.5 |
|
1554 |
*/ |
|
1555 |
public StackTraceElement[] getStackTrace() { |
|
1556 |
if (this != Thread.currentThread()) { |
|
1557 |
// check for getStackTrace permission |
|
1558 |
SecurityManager security = System.getSecurityManager(); |
|
1559 |
if (security != null) { |
|
1560 |
security.checkPermission( |
|
1561 |
SecurityConstants.GET_STACK_TRACE_PERMISSION); |
|
1562 |
} |
|
1563 |
// optimization so we do not call into the vm for threads that |
|
1564 |
// have not yet started or have terminated |
|
1565 |
if (!isAlive()) { |
|
1566 |
return EMPTY_STACK_TRACE; |
|
1567 |
} |
|
1568 |
StackTraceElement[][] stackTraceArray = dumpThreads(new Thread[] {this}); |
|
1569 |
StackTraceElement[] stackTrace = stackTraceArray[0]; |
|
1570 |
// a thread that was alive during the previous isAlive call may have |
|
1571 |
// since terminated, therefore not having a stacktrace. |
|
1572 |
if (stackTrace == null) { |
|
1573 |
stackTrace = EMPTY_STACK_TRACE; |
|
1574 |
} |
|
1575 |
return stackTrace; |
|
1576 |
} else { |
|
1577 |
// Don't need JVM help for current thread |
|
1578 |
return (new Exception()).getStackTrace(); |
|
1579 |
} |
|
1580 |
} |
|
1581 |
||
1582 |
/** |
|
1583 |
* Returns a map of stack traces for all live threads. |
|
1584 |
* The map keys are threads and each map value is an array of |
|
1585 |
* <tt>StackTraceElement</tt> that represents the stack dump |
|
1586 |
* of the corresponding <tt>Thread</tt>. |
|
1587 |
* The returned stack traces are in the format specified for |
|
1588 |
* the {@link #getStackTrace getStackTrace} method. |
|
1589 |
* |
|
1590 |
* <p>The threads may be executing while this method is called. |
|
1591 |
* The stack trace of each thread only represents a snapshot and |
|
1592 |
* each stack trace may be obtained at different time. A zero-length |
|
1593 |
* array will be returned in the map value if the virtual machine has |
|
1594 |
* no stack trace information about a thread. |
|
1595 |
* |
|
1596 |
* <p>If there is a security manager, then the security manager's |
|
1597 |
* <tt>checkPermission</tt> method is called with a |
|
1598 |
* <tt>RuntimePermission("getStackTrace")</tt> permission as well as |
|
1599 |
* <tt>RuntimePermission("modifyThreadGroup")</tt> permission |
|
1600 |
* to see if it is ok to get the stack trace of all threads. |
|
1601 |
* |
|
1602 |
* @return a <tt>Map</tt> from <tt>Thread</tt> to an array of |
|
1603 |
* <tt>StackTraceElement</tt> that represents the stack trace of |
|
1604 |
* the corresponding thread. |
|
1605 |
* |
|
1606 |
* @throws SecurityException |
|
1607 |
* if a security manager exists and its |
|
1608 |
* <tt>checkPermission</tt> method doesn't allow |
|
1609 |
* getting the stack trace of thread. |
|
1610 |
* @see #getStackTrace |
|
1611 |
* @see SecurityManager#checkPermission |
|
1612 |
* @see RuntimePermission |
|
1613 |
* @see Throwable#getStackTrace |
|
1614 |
* |
|
1615 |
* @since 1.5 |
|
1616 |
*/ |
|
1617 |
public static Map<Thread, StackTraceElement[]> getAllStackTraces() { |
|
1618 |
// check for getStackTrace permission |
|
1619 |
SecurityManager security = System.getSecurityManager(); |
|
1620 |
if (security != null) { |
|
1621 |
security.checkPermission( |
|
1622 |
SecurityConstants.GET_STACK_TRACE_PERMISSION); |
|
1623 |
security.checkPermission( |
|
1624 |
SecurityConstants.MODIFY_THREADGROUP_PERMISSION); |
|
1625 |
} |
|
1626 |
||
1627 |
// Get a snapshot of the list of all threads |
|
1628 |
Thread[] threads = getThreads(); |
|
1629 |
StackTraceElement[][] traces = dumpThreads(threads); |
|
1630 |
Map<Thread, StackTraceElement[]> m |
|
1631 |
= new HashMap<Thread, StackTraceElement[]>(threads.length); |
|
1632 |
for (int i = 0; i < threads.length; i++) { |
|
1633 |
StackTraceElement[] stackTrace = traces[i]; |
|
1634 |
if (stackTrace != null) { |
|
1635 |
m.put(threads[i], stackTrace); |
|
1636 |
} |
|
1637 |
// else terminated so we don't put it in the map |
|
1638 |
} |
|
1639 |
return m; |
|
1640 |
} |
|
1641 |
||
1642 |
||
1643 |
private static final RuntimePermission SUBCLASS_IMPLEMENTATION_PERMISSION = |
|
1644 |
new RuntimePermission("enableContextClassLoaderOverride"); |
|
1645 |
||
1646 |
/** cache of subclass security audit results */ |
|
2069
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1647 |
/* Replace with ConcurrentReferenceHashMap when/if it appears in a future |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1648 |
* release */ |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1649 |
private static class Caches { |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1650 |
/** cache of subclass security audit results */ |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1651 |
static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits = |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1652 |
new ConcurrentHashMap<WeakClassKey,Boolean>(); |
2 | 1653 |
|
2069
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1654 |
/** queue for WeakReferences to audited subclasses */ |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1655 |
static final ReferenceQueue<Class<?>> subclassAuditsQueue = |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1656 |
new ReferenceQueue<Class<?>>(); |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1657 |
} |
2 | 1658 |
|
1659 |
/** |
|
1660 |
* Verifies that this (possibly subclass) instance can be constructed |
|
1661 |
* without violating security constraints: the subclass must not override |
|
1662 |
* security-sensitive non-final methods, or else the |
|
1663 |
* "enableContextClassLoaderOverride" RuntimePermission is checked. |
|
1664 |
*/ |
|
1665 |
private static boolean isCCLOverridden(Class cl) { |
|
1666 |
if (cl == Thread.class) |
|
1667 |
return false; |
|
2069
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1668 |
|
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1669 |
processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits); |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1670 |
WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue); |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1671 |
Boolean result = Caches.subclassAudits.get(key); |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1672 |
if (result == null) { |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1673 |
result = Boolean.valueOf(auditSubclass(cl)); |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1674 |
Caches.subclassAudits.putIfAbsent(key, result); |
2 | 1675 |
} |
2069
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1676 |
|
2 | 1677 |
return result.booleanValue(); |
1678 |
} |
|
1679 |
||
1680 |
/** |
|
1681 |
* Performs reflective checks on given subclass to verify that it doesn't |
|
1682 |
* override security-sensitive non-final methods. Returns true if the |
|
1683 |
* subclass overrides any of the methods, false otherwise. |
|
1684 |
*/ |
|
1685 |
private static boolean auditSubclass(final Class subcl) { |
|
1686 |
Boolean result = AccessController.doPrivileged( |
|
1687 |
new PrivilegedAction<Boolean>() { |
|
1688 |
public Boolean run() { |
|
1689 |
for (Class cl = subcl; |
|
1690 |
cl != Thread.class; |
|
1691 |
cl = cl.getSuperclass()) |
|
1692 |
{ |
|
1693 |
try { |
|
1694 |
cl.getDeclaredMethod("getContextClassLoader", new Class[0]); |
|
1695 |
return Boolean.TRUE; |
|
1696 |
} catch (NoSuchMethodException ex) { |
|
1697 |
} |
|
1698 |
try { |
|
1699 |
Class[] params = {ClassLoader.class}; |
|
1700 |
cl.getDeclaredMethod("setContextClassLoader", params); |
|
1701 |
return Boolean.TRUE; |
|
1702 |
} catch (NoSuchMethodException ex) { |
|
1703 |
} |
|
1704 |
} |
|
1705 |
return Boolean.FALSE; |
|
1706 |
} |
|
1707 |
} |
|
1708 |
); |
|
1709 |
return result.booleanValue(); |
|
1710 |
} |
|
1711 |
||
1712 |
private native static StackTraceElement[][] dumpThreads(Thread[] threads); |
|
1713 |
private native static Thread[] getThreads(); |
|
1714 |
||
1715 |
/** |
|
1716 |
* Returns the identifier of this Thread. The thread ID is a positive |
|
1717 |
* <tt>long</tt> number generated when this thread was created. |
|
1718 |
* The thread ID is unique and remains unchanged during its lifetime. |
|
1719 |
* When a thread is terminated, this thread ID may be reused. |
|
1720 |
* |
|
1721 |
* @return this thread's ID. |
|
1722 |
* @since 1.5 |
|
1723 |
*/ |
|
1724 |
public long getId() { |
|
1725 |
return tid; |
|
1726 |
} |
|
1727 |
||
1728 |
/** |
|
1729 |
* A thread state. A thread can be in one of the following states: |
|
1730 |
* <ul> |
|
1731 |
* <li>{@link #NEW}<br> |
|
1732 |
* A thread that has not yet started is in this state. |
|
1733 |
* </li> |
|
1734 |
* <li>{@link #RUNNABLE}<br> |
|
1735 |
* A thread executing in the Java virtual machine is in this state. |
|
1736 |
* </li> |
|
1737 |
* <li>{@link #BLOCKED}<br> |
|
1738 |
* A thread that is blocked waiting for a monitor lock |
|
1739 |
* is in this state. |
|
1740 |
* </li> |
|
1741 |
* <li>{@link #WAITING}<br> |
|
1742 |
* A thread that is waiting indefinitely for another thread to |
|
1743 |
* perform a particular action is in this state. |
|
1744 |
* </li> |
|
1745 |
* <li>{@link #TIMED_WAITING}<br> |
|
1746 |
* A thread that is waiting for another thread to perform an action |
|
1747 |
* for up to a specified waiting time is in this state. |
|
1748 |
* </li> |
|
1749 |
* <li>{@link #TERMINATED}<br> |
|
1750 |
* A thread that has exited is in this state. |
|
1751 |
* </li> |
|
1752 |
* </ul> |
|
1753 |
* |
|
1754 |
* <p> |
|
1755 |
* A thread can be in only one state at a given point in time. |
|
1756 |
* These states are virtual machine states which do not reflect |
|
1757 |
* any operating system thread states. |
|
1758 |
* |
|
1759 |
* @since 1.5 |
|
1760 |
* @see #getState |
|
1761 |
*/ |
|
1762 |
public enum State { |
|
1763 |
/** |
|
1764 |
* Thread state for a thread which has not yet started. |
|
1765 |
*/ |
|
1766 |
NEW, |
|
1767 |
||
1768 |
/** |
|
1769 |
* Thread state for a runnable thread. A thread in the runnable |
|
1770 |
* state is executing in the Java virtual machine but it may |
|
1771 |
* be waiting for other resources from the operating system |
|
1772 |
* such as processor. |
|
1773 |
*/ |
|
1774 |
RUNNABLE, |
|
1775 |
||
1776 |
/** |
|
1777 |
* Thread state for a thread blocked waiting for a monitor lock. |
|
1778 |
* A thread in the blocked state is waiting for a monitor lock |
|
1779 |
* to enter a synchronized block/method or |
|
1780 |
* reenter a synchronized block/method after calling |
|
1781 |
* {@link Object#wait() Object.wait}. |
|
1782 |
*/ |
|
1783 |
BLOCKED, |
|
1784 |
||
1785 |
/** |
|
1786 |
* Thread state for a waiting thread. |
|
1787 |
* A thread is in the waiting state due to calling one of the |
|
1788 |
* following methods: |
|
1789 |
* <ul> |
|
1790 |
* <li>{@link Object#wait() Object.wait} with no timeout</li> |
|
1791 |
* <li>{@link #join() Thread.join} with no timeout</li> |
|
1792 |
* <li>{@link LockSupport#park() LockSupport.park}</li> |
|
1793 |
* </ul> |
|
1794 |
* |
|
1795 |
* <p>A thread in the waiting state is waiting for another thread to |
|
1796 |
* perform a particular action. |
|
1797 |
* |
|
1798 |
* For example, a thread that has called <tt>Object.wait()</tt> |
|
1799 |
* on an object is waiting for another thread to call |
|
1800 |
* <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on |
|
1801 |
* that object. A thread that has called <tt>Thread.join()</tt> |
|
1802 |
* is waiting for a specified thread to terminate. |
|
1803 |
*/ |
|
1804 |
WAITING, |
|
1805 |
||
1806 |
/** |
|
1807 |
* Thread state for a waiting thread with a specified waiting time. |
|
1808 |
* A thread is in the timed waiting state due to calling one of |
|
1809 |
* the following methods with a specified positive waiting time: |
|
1810 |
* <ul> |
|
1811 |
* <li>{@link #sleep Thread.sleep}</li> |
|
1812 |
* <li>{@link Object#wait(long) Object.wait} with timeout</li> |
|
1813 |
* <li>{@link #join(long) Thread.join} with timeout</li> |
|
1814 |
* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li> |
|
1815 |
* <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li> |
|
1816 |
* </ul> |
|
1817 |
*/ |
|
1818 |
TIMED_WAITING, |
|
1819 |
||
1820 |
/** |
|
1821 |
* Thread state for a terminated thread. |
|
1822 |
* The thread has completed execution. |
|
1823 |
*/ |
|
1824 |
TERMINATED; |
|
1825 |
} |
|
1826 |
||
1827 |
/** |
|
1828 |
* Returns the state of this thread. |
|
1829 |
* This method is designed for use in monitoring of the system state, |
|
1830 |
* not for synchronization control. |
|
1831 |
* |
|
1832 |
* @return this thread's state. |
|
1833 |
* @since 1.5 |
|
1834 |
*/ |
|
1835 |
public State getState() { |
|
1836 |
// get current thread state |
|
1837 |
return sun.misc.VM.toThreadState(threadStatus); |
|
1838 |
} |
|
1839 |
||
1840 |
// Added in JSR-166 |
|
1841 |
||
1842 |
/** |
|
1843 |
* Interface for handlers invoked when a <tt>Thread</tt> abruptly |
|
1844 |
* terminates due to an uncaught exception. |
|
1845 |
* <p>When a thread is about to terminate due to an uncaught exception |
|
1846 |
* the Java Virtual Machine will query the thread for its |
|
1847 |
* <tt>UncaughtExceptionHandler</tt> using |
|
1848 |
* {@link #getUncaughtExceptionHandler} and will invoke the handler's |
|
1849 |
* <tt>uncaughtException</tt> method, passing the thread and the |
|
1850 |
* exception as arguments. |
|
1851 |
* If a thread has not had its <tt>UncaughtExceptionHandler</tt> |
|
1852 |
* explicitly set, then its <tt>ThreadGroup</tt> object acts as its |
|
1853 |
* <tt>UncaughtExceptionHandler</tt>. If the <tt>ThreadGroup</tt> object |
|
1854 |
* has no |
|
1855 |
* special requirements for dealing with the exception, it can forward |
|
1856 |
* the invocation to the {@linkplain #getDefaultUncaughtExceptionHandler |
|
1857 |
* default uncaught exception handler}. |
|
1858 |
* |
|
1859 |
* @see #setDefaultUncaughtExceptionHandler |
|
1860 |
* @see #setUncaughtExceptionHandler |
|
1861 |
* @see ThreadGroup#uncaughtException |
|
1862 |
* @since 1.5 |
|
1863 |
*/ |
|
1864 |
public interface UncaughtExceptionHandler { |
|
1865 |
/** |
|
1866 |
* Method invoked when the given thread terminates due to the |
|
1867 |
* given uncaught exception. |
|
1868 |
* <p>Any exception thrown by this method will be ignored by the |
|
1869 |
* Java Virtual Machine. |
|
1870 |
* @param t the thread |
|
1871 |
* @param e the exception |
|
1872 |
*/ |
|
1873 |
void uncaughtException(Thread t, Throwable e); |
|
1874 |
} |
|
1875 |
||
1876 |
// null unless explicitly set |
|
1877 |
private volatile UncaughtExceptionHandler uncaughtExceptionHandler; |
|
1878 |
||
1879 |
// null unless explicitly set |
|
1880 |
private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler; |
|
1881 |
||
1882 |
/** |
|
1883 |
* Set the default handler invoked when a thread abruptly terminates |
|
1884 |
* due to an uncaught exception, and no other handler has been defined |
|
1885 |
* for that thread. |
|
1886 |
* |
|
1887 |
* <p>Uncaught exception handling is controlled first by the thread, then |
|
1888 |
* by the thread's {@link ThreadGroup} object and finally by the default |
|
1889 |
* uncaught exception handler. If the thread does not have an explicit |
|
1890 |
* uncaught exception handler set, and the thread's thread group |
|
1891 |
* (including parent thread groups) does not specialize its |
|
1892 |
* <tt>uncaughtException</tt> method, then the default handler's |
|
1893 |
* <tt>uncaughtException</tt> method will be invoked. |
|
1894 |
* <p>By setting the default uncaught exception handler, an application |
|
1895 |
* can change the way in which uncaught exceptions are handled (such as |
|
1896 |
* logging to a specific device, or file) for those threads that would |
|
1897 |
* already accept whatever "default" behavior the system |
|
1898 |
* provided. |
|
1899 |
* |
|
1900 |
* <p>Note that the default uncaught exception handler should not usually |
|
1901 |
* defer to the thread's <tt>ThreadGroup</tt> object, as that could cause |
|
1902 |
* infinite recursion. |
|
1903 |
* |
|
1904 |
* @param eh the object to use as the default uncaught exception handler. |
|
1905 |
* If <tt>null</tt> then there is no default handler. |
|
1906 |
* |
|
1907 |
* @throws SecurityException if a security manager is present and it |
|
1908 |
* denies <tt>{@link RuntimePermission} |
|
1909 |
* ("setDefaultUncaughtExceptionHandler")</tt> |
|
1910 |
* |
|
1911 |
* @see #setUncaughtExceptionHandler |
|
1912 |
* @see #getUncaughtExceptionHandler |
|
1913 |
* @see ThreadGroup#uncaughtException |
|
1914 |
* @since 1.5 |
|
1915 |
*/ |
|
1916 |
public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) { |
|
1917 |
SecurityManager sm = System.getSecurityManager(); |
|
1918 |
if (sm != null) { |
|
1919 |
sm.checkPermission( |
|
1920 |
new RuntimePermission("setDefaultUncaughtExceptionHandler") |
|
1921 |
); |
|
1922 |
} |
|
1923 |
||
1924 |
defaultUncaughtExceptionHandler = eh; |
|
1925 |
} |
|
1926 |
||
1927 |
/** |
|
1928 |
* Returns the default handler invoked when a thread abruptly terminates |
|
1929 |
* due to an uncaught exception. If the returned value is <tt>null</tt>, |
|
1930 |
* there is no default. |
|
1931 |
* @since 1.5 |
|
1932 |
* @see #setDefaultUncaughtExceptionHandler |
|
1933 |
*/ |
|
1934 |
public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler(){ |
|
1935 |
return defaultUncaughtExceptionHandler; |
|
1936 |
} |
|
1937 |
||
1938 |
/** |
|
1939 |
* Returns the handler invoked when this thread abruptly terminates |
|
1940 |
* due to an uncaught exception. If this thread has not had an |
|
1941 |
* uncaught exception handler explicitly set then this thread's |
|
1942 |
* <tt>ThreadGroup</tt> object is returned, unless this thread |
|
1943 |
* has terminated, in which case <tt>null</tt> is returned. |
|
1944 |
* @since 1.5 |
|
1945 |
*/ |
|
1946 |
public UncaughtExceptionHandler getUncaughtExceptionHandler() { |
|
1947 |
return uncaughtExceptionHandler != null ? |
|
1948 |
uncaughtExceptionHandler : group; |
|
1949 |
} |
|
1950 |
||
1951 |
/** |
|
1952 |
* Set the handler invoked when this thread abruptly terminates |
|
1953 |
* due to an uncaught exception. |
|
1954 |
* <p>A thread can take full control of how it responds to uncaught |
|
1955 |
* exceptions by having its uncaught exception handler explicitly set. |
|
1956 |
* If no such handler is set then the thread's <tt>ThreadGroup</tt> |
|
1957 |
* object acts as its handler. |
|
1958 |
* @param eh the object to use as this thread's uncaught exception |
|
1959 |
* handler. If <tt>null</tt> then this thread has no explicit handler. |
|
1960 |
* @throws SecurityException if the current thread is not allowed to |
|
1961 |
* modify this thread. |
|
1962 |
* @see #setDefaultUncaughtExceptionHandler |
|
1963 |
* @see ThreadGroup#uncaughtException |
|
1964 |
* @since 1.5 |
|
1965 |
*/ |
|
1966 |
public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) { |
|
1967 |
checkAccess(); |
|
1968 |
uncaughtExceptionHandler = eh; |
|
1969 |
} |
|
1970 |
||
1971 |
/** |
|
1972 |
* Dispatch an uncaught exception to the handler. This method is |
|
1973 |
* intended to be called only by the JVM. |
|
1974 |
*/ |
|
1975 |
private void dispatchUncaughtException(Throwable e) { |
|
1976 |
getUncaughtExceptionHandler().uncaughtException(this, e); |
|
1977 |
} |
|
1978 |
||
2069
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1979 |
/** |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1980 |
* Removes from the specified map any keys that have been enqueued |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1981 |
* on the specified reference queue. |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1982 |
*/ |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1983 |
static void processQueue(ReferenceQueue<Class<?>> queue, |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1984 |
ConcurrentMap<? extends |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1985 |
WeakReference<Class<?>>, ?> map) |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1986 |
{ |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1987 |
Reference<? extends Class<?>> ref; |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1988 |
while((ref = queue.poll()) != null) { |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1989 |
map.remove(ref); |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1990 |
} |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1991 |
} |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1992 |
|
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1993 |
/** |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1994 |
* Weak key for Class objects. |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1995 |
**/ |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1996 |
static class WeakClassKey extends WeakReference<Class<?>> { |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1997 |
/** |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1998 |
* saved value of the referent's identity hash code, to maintain |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
1999 |
* a consistent hash code after the referent has been cleared |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2000 |
*/ |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2001 |
private final int hash; |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2002 |
|
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2003 |
/** |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2004 |
* Create a new WeakClassKey to the given object, registered |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2005 |
* with a queue. |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2006 |
*/ |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2007 |
WeakClassKey(Class<?> cl, ReferenceQueue<Class<?>> refQueue) { |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2008 |
super(cl, refQueue); |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2009 |
hash = System.identityHashCode(cl); |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2010 |
} |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2011 |
|
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2012 |
/** |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2013 |
* Returns the identity hash code of the original referent. |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2014 |
*/ |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2015 |
@Override |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2016 |
public int hashCode() { |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2017 |
return hash; |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2018 |
} |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2019 |
|
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2020 |
/** |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2021 |
* Returns true if the given object is this identical |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2022 |
* WeakClassKey instance, or, if this object's referent has not |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2023 |
* been cleared, if the given object is another WeakClassKey |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2024 |
* instance with the identical non-null referent as this one. |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2025 |
*/ |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2026 |
@Override |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2027 |
public boolean equals(Object obj) { |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2028 |
if (obj == this) |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2029 |
return true; |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2030 |
|
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2031 |
if (obj instanceof WeakClassKey) { |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2032 |
Object referent = get(); |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2033 |
return (referent != null) && |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2034 |
(referent == ((WeakClassKey) obj).get()); |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2035 |
} else { |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2036 |
return false; |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2037 |
} |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2038 |
} |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2039 |
} |
2cd4a0aa917f
6806649: synchronization bottleneck when constructing Thread subclasses
chegar
parents:
1148
diff
changeset
|
2040 |
|
2 | 2041 |
/* Some private helper methods */ |
2042 |
private native void setPriority0(int newPriority); |
|
2043 |
private native void stop0(Object o); |
|
2044 |
private native void suspend0(); |
|
2045 |
private native void resume0(); |
|
2046 |
private native void interrupt0(); |
|
2047 |
} |