1 package java.lang;
2
3 import java.lang.ref.Reference;
4 import java.lang.ref.ReferenceQueue;
5 import java.lang.ref.WeakReference;
6 import java.security.AccessController;
7 import java.security.AccessControlContext;
8 import java.security.PrivilegedAction;
9 import java.util.Map;
10 import java.util.HashMap;
11 import java.util.concurrent.ConcurrentHashMap;
12 import java.util.concurrent.ConcurrentMap;
13 import java.util.concurrent.locks.LockSupport;
14
15 import sun.nio.ch.Interruptible;
16 import sun.reflect.CallerSensitive;
17 import sun.reflect.Reflection;
18 import sun.security.util.SecurityConstants;
19
20 /*
21 Every thread has a priority. Threads with higher priority are executed in preference to threads
22 with lower priority.
23 Each thread may or may not also be marked as a daemon. When code running in some thread creates a
24 new <code>Thread</code> object,the new thread has its priority initially set equal to the priority
25 of the creating thread, and is a daemon thread if and only if the creating thread is a daemon.
26
27 When a Java Virtual Machine starts up, there is usually a single non-daemon thread (which typically
28 calls the method named <code>main</code> of some designated class). The Java Virtual Machine continues
29 to execute threads until either of the following occurs:
30 1.The <code>exit</code> method of class <code>Runtime</code> has been called and the security manager
31 has permitted the exit operation to take place.
32 2.All threads that are not daemon threads have died, either by returning from the call to the
33 <code>run</code> method or by throwing an exception that propagates beyond the <code>run</code> method.
34
35 Every thread has a name for identification purposes. More than one thread may have the same name. If a name
36 is not specified when a thread is created, a new name is generated for it.Unless otherwise noted, passing a
37 {@code null} argument to a constructor or method in this class will cause a {@link NullPointerException} to be thrown.
38 */
39 public class Thread implements Runnable {
40 private static native void registerNatives();
41
42 static {
43 registerNatives();
44 }
45
46 private volatile char name[];
47 private int priority;
48 private Thread threadQ;
49 private long eetop;
50
51 //是否单步执行线程
52 private boolean single_step;
53
54 //是否为守护线程
55 private boolean daemon = false;
56
57 //JVM状态
58 private boolean stillborn = false;
59
60 //run方法执行的目标代码
61 private Runnable target;
62
63 //线程所属的线程组
64 private ThreadGroup group;
65
66 //线程的类加载器
67 private ClassLoader contextClassLoader;
68
69 //线程继承的AccessControlContext
70 private AccessControlContext inheritedAccessControlContext;
71
72 //默认生成的线程名"Thread-" + nextThreadNum()
73 private static int threadInitNumber;
74
75 private static synchronized int nextThreadNum() {
76 return threadInitNumber++;
77 }
78
79 ThreadLocal.ThreadLocalMap threadLocals = null;
80
81 ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
82
83 //线程请求栈的深度,如果线程创建者未指定栈深度则其值为0,stackSize如何用完全取决于虚拟机,有的虚拟机会忽略stackSize
84 private long stackSize;
85
86 //本地线程终止后,JVM私有的值
87 private long nativeParkEventPointer;
88
89 //线程id
90 private long tid;
91
92 //用于生成线程ID
93 private static long threadSeqNumber;
94
95 //为工具提供的线程状态值,0表示当前线程还未运行
96 private volatile int threadStatus = 0;
97
98 //获取下一个线程tid
99 private static synchronized long nextThreadID() {
100 return ++threadSeqNumber;
101 }
102
103 /*
104 parkBlocker用于调用java.util.concurrent.locks.LockSupport.park方法
105 通过java.util.concurrent.locks.LockSupport.setBlocker方法set
106 通过java.util.concurrent.locks.LockSupport.getBlocker方法get
107 */
108 volatile Object parkBlocker;
109
110 /*
111 The object in which this thread is blocked in an interruptible I/O operation, if any.
112 The blocker's interrupt method should be invoked after setting this thread's interrupt status.
113 */
114 private volatile Interruptible blocker;
115 private final Object blockerLock = new Object();
116
117 void blockedOn(Interruptible b) {
118 synchronized (blockerLock) {
119 blocker = b;
120 }
121 }
122
123 //线程的最低优先级
124 public final static int MIN_PRIORITY = 1;
125
126 //线程的默认优先级
127 public final static int NORM_PRIORITY = 5;
128
129 //线程的最高优先级
130 public final static int MAX_PRIORITY = 10;
131
132 //返回当前正在执行线程对象的引用
133 public static native Thread currentThread();
134
135 /*
136 A hint to the scheduler that the current thread is willing to yield
137 its current use of a processor. The scheduler is free to ignore this hint.
138 */
139 public static native void yield();
140
141 //调用sleep方法会使得当前线程临时停止执行指定毫秒数,sleep不释放锁
142 public static native void sleep(long millis) throws InterruptedException;
143
144 public static void sleep(long millis, int nanos)
145 throws InterruptedException {
146 if (millis < 0) {
147 throw new IllegalArgumentException("timeout value is negative");
148 }
149
150 if (nanos < 0 || nanos > 999999) {
151 throw new IllegalArgumentException(
152 "nanosecond timeout value out of range");
153 }
154
155 if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
156 millis++;
157 }
158
159 sleep(millis);
160 }
161
162 private void init(ThreadGroup g, Runnable target, String name,
163 long stackSize) {
164 init(g, target, name, stackSize, null);
165 }
166
167 private void init(ThreadGroup g, Runnable target, String name,
168 long stackSize, AccessControlContext acc) {
169 if (name == null) {
170 throw new NullPointerException("name cannot be null");
171 }
172
173 this.name = name.toCharArray();
174
175 Thread parent = currentThread();
176 SecurityManager security = System.getSecurityManager();
177 if (g == null) {
178 if (security != null) {
179 g = security.getThreadGroup();
180 }
181
182 if (g == null) {
183 g = parent.getThreadGroup();
184 }
185 }
186
187 g.checkAccess();
188
189 if (security != null) {
190 if (isCCLOverridden(getClass())) {
191 security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
192 }
193 }
194
195 g.addUnstarted();
196
197 this.group = g;
198 this.daemon = parent.isDaemon();
199 this.priority = parent.getPriority();
200 if (security == null || isCCLOverridden(parent.getClass()))
201 this.contextClassLoader = parent.getContextClassLoader();
202 else
203 this.contextClassLoader = parent.contextClassLoader;
204 this.inheritedAccessControlContext =
205 acc != null ? acc : AccessController.getContext();
206 this.target = target;
207 setPriority(priority);
208 if (parent.inheritableThreadLocals != null)
209 this.inheritableThreadLocals =
210 ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
211 this.stackSize = stackSize;
212
213 tid = nextThreadID();
214 }
215
216 //线程不支持Object的浅拷贝,取而代之的是构造一个新的线程
217 @Override
218 protected Object clone() throws CloneNotSupportedException {
219 throw new CloneNotSupportedException();
220 }
221
222 public Thread() {
223 init(null, null, "Thread-" + nextThreadNum(), 0);
224 }
225
226 public Thread(Runnable target) {
227 init(null, target, "Thread-" + nextThreadNum(), 0);
228 }
229
230 Thread(Runnable target, AccessControlContext acc) {
231 init(null, target, "Thread-" + nextThreadNum(), 0, acc);
232 }
233
234 public Thread(ThreadGroup group, Runnable target) {
235 init(group, target, "Thread-" + nextThreadNum(), 0);
236 }
237
238 public Thread(String name) {
239 init(null, null, name, 0);
240 }
241
242 public Thread(ThreadGroup group, String name) {
243 init(group, null, name, 0);
244 }
245
246 public Thread(Runnable target, String name) {
247 init(null, target, name, 0);
248 }
249
250 public Thread(ThreadGroup group, Runnable target, String name) {
251 init(group, target, name, 0);
252 }
253
254 public Thread(ThreadGroup group, Runnable target, String name,
255 long stackSize) {
256 init(group, target, name, stackSize);
257 }
258
259 /*
260 Causes this thread to begin execution; the Java Virtual Machine calls
261 the <code>run</code> method of this thread.
262 The result is that two threads are running concurrently: the current thread
263 (which returns from the call to the <code>start</code> method) and the other
264 thread (which executes its <code>run</code> method).
265
266 public class ThreadTest {
267 public static void main(String[] args) throws InterruptedException {
268 Thread t1=new Thread(new Runnable() {
269 @Override
270 public void run() {
271 System.out.println("sakura");
272 }
273 });
274 t1.start();
275 t1.join();
276 t1.start();
277 }
278 }
279
280 sakura
281 Exception in thread "main" java.lang.IllegalThreadStateException
282 at java.lang.Thread.start(Thread.java:705)
283 at ThreadTest.main(ThreadTest.java:11)
284 */
285 public synchronized void start() {
286 //threadStatus=0表示线程处于NEW状态
287 if (threadStatus != 0)
288 throw new IllegalThreadStateException();
289
290 group.add(this);
291
292 boolean started = false;
293 try {
294 start0();
295 started = true;
296 } finally {
297 try {
298 if (!started) {
299 group.threadStartFailed(this);
300 }
301 } catch (Throwable ignore) {
302
303 }
304 }
305 }
306
307 private native void start0();
308
309 @Override
310 public void run() {
311 if (target != null) {
312 target.run();
313 }
314 }
315
316 //This method is called by the system to give a Thread a chance to clean up before it actually exits.
317 private void exit() {
318 if (group != null) {
319 group.threadTerminated(this);
320 group = null;
321 }
322 target = null;
323 threadLocals = null;
324 inheritableThreadLocals = null;
325 inheritedAccessControlContext = null;
326 blocker = null;
327 uncaughtExceptionHandler = null;
328 }
329
330 @Deprecated
331 public final void stop() {
332 SecurityManager security = System.getSecurityManager();
333 if (security != null) {
334 checkAccess();
335 if (this != Thread.currentThread()) {
336 security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
337 }
338 }
339 if (threadStatus != 0) {
340 resume();
341 }
342
343 stop0(new ThreadDeath());
344 }
345
346 @Deprecated
347 public final synchronized void stop(Throwable obj) {
348 throw new UnsupportedOperationException();
349 }
350
351 /*
352 中断当前线程,如果不是当前线程中断自己,会调用checkAccess方法,这可能会抛出SecurityException
353 1.如果当前线程由于调用wait、join或sleep方法而阻塞,则中断状态会被清除且会抛出InterruptedException
354 2.如果线程由于java.nio.channels.InterruptibleChannel类中的InterruptibleChannel的I/O操作而被阻塞,
355 调用interrupt方法会使通道关闭且线程的中断状态会被重置并抛出ClosedByInterruptException
356 3.如果当前线程由于java.nio.channels.Selector而被阻塞,则线程的中断状态会被重置,且会立即从selection操作
357 返回一个非零值,这就和java.nio.channels.Selector的wakeup()方法被调用一样
358 如果以上条件都不成立,那么线程的中断状态被重置,中断一个非活跃线程不产生影响
359 */
360 public void interrupt() {
361 if (this != Thread.currentThread())
362 checkAccess();
363
364 synchronized (blockerLock) {
365 Interruptible b = blocker;
366 if (b != null) {
367 interrupt0();
368 b.interrupt(this);
369 return;
370 }
371 }
372 interrupt0();
373 }
374
375 /*
376 测试当前线程是否被中断,并且清除中断状态
377 In other words, if this method were to be called twice in succession, the second
378 call would return false (unless the current thread were interrupted again, after
379 the first call had cleared its interrupted status and before the second call had examined it).
380
381 A thread interruption ignored because a thread was not alive at the time of the interrupt will
382 be reflected by this method returning false.
383 */
384 public static boolean interrupted() {
385 return currentThread().isInterrupted(true);
386 }
387
388 //测试当前线程是否被中断,但不清除中断状态
389 public boolean isInterrupted() {
390 return isInterrupted(false);
391 }
392
393 private native boolean isInterrupted(boolean ClearInterrupted);
394
395 @Deprecated
396 public void destroy() {
397 throw new NoSuchMethodError();
398 }
399
400 /*
401 判断线程是否处于存活状态
402 A thread is alive if it has been started and has not yet died.
403 */
404 public final native boolean isAlive();
405
406 @Deprecated
407 public final void suspend() {
408 checkAccess();
409 suspend0();
410 }
411
412 @Deprecated
413 public final void resume() {
414 checkAccess();
415 resume0();
416 }
417
418 //设置线程的优先级
419 public final void setPriority(int newPriority) {
420 ThreadGroup g;
421 checkAccess();
422 if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
423 throw new IllegalArgumentException();
424 }
425 if ((g = getThreadGroup()) != null) {
426 if (newPriority > g.getMaxPriority()) {
427 newPriority = g.getMaxPriority();
428 }
429 setPriority0(priority = newPriority);
430 }
431 }
432
433 //返回线程优先级
434 public final int getPriority() {
435 return priority;
436 }
437
438 //设置线程的name
439 public final synchronized void setName(String name) {
440 checkAccess();
441 this.name = name.toCharArray();
442 if (threadStatus != 0) {
443 setNativeName(name);
444 }
445 }
446
447 //返回线程的name
448 public final String getName() {
449 return new String(name, true);
450 }
451
452 //返回线程所属的线程组,如果线程已经died,那么会返回null
453 public final ThreadGroup getThreadGroup() {
454 return group;
455 }
456
457 //返回当前线程所在线程组的线程数的估计值
458 public static int activeCount() {
459 return currentThread().getThreadGroup().activeCount();
460 }
461
462 public static int enumerate(Thread tarray[]) {
463 return currentThread().getThreadGroup().enumerate(tarray);
464 }
465
466 @Deprecated
467 public native int countStackFrames();
468
469 /*
470 最多等待millis时长当前线程就会死亡,millis=0则要持续等待
471 It is recommended that applications not use {@code wait},
472 {@code notify}, or {@code notifyAll} on {@code Thread} instances.
473 */
474 public final synchronized void join(long millis)
475 throws InterruptedException {
476 long base = System.currentTimeMillis();
477 long now = 0;
478
479 if (millis < 0) {
480 throw new IllegalArgumentException("timeout value is negative");
481 }
482
483 if (millis == 0) {
484 while (isAlive()) {
485 wait(0);
486 }
487 } else {
488 while (isAlive()) {
489 long delay = millis - now;
490 if (delay <= 0) {
491 break;
492 }
493 wait(delay);
494 now = System.currentTimeMillis() - base;
495 }
496 }
497 }
498
499 //最多等待millis微秒+nanos纳秒时长当前线程就会死亡
500 public final synchronized void join(long millis, int nanos)
501 throws InterruptedException {
502
503 if (millis < 0) {
504 throw new IllegalArgumentException("timeout value is negative");
505 }
506
507 if (nanos < 0 || nanos > 999999) {
508 throw new IllegalArgumentException(
509 "nanosecond timeout value out of range");
510 }
511
512 if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
513 millis++;
514 }
515
516 join(millis);
517 }
518
519 //等待一直到线程死亡
520 public final void join() throws InterruptedException {
521 join(0);
522 }
523
524 /*
525 Prints a stack trace of the current thread to the standard error stream.
526 This method is used only for debugging.
527 */
528 public static void dumpStack() {
529 new Exception("Stack trace").printStackTrace();
530 }
531
532 /*
533 设置当前线程为守护线程或用户线程
534 只有当所有运行中的线程都为守护线程时JVM才会退出
535 setDaemon方法必须在线程调用start方法之前调用
536 */
537 public final void setDaemon(boolean on) {
538 checkAccess();
539 if (isAlive()) {
540 throw new IllegalThreadStateException();
541 }
542 daemon = on;
543 }
544
545 //判断当前线程是否为守护线程
546 public final boolean isDaemon() {
547 return daemon;
548 }
549
550 //确定当前运行线程是否具有修改线程的权限
551 public final void checkAccess() {
552 SecurityManager security = System.getSecurityManager();
553 if (security != null) {
554 security.checkAccess(this);
555 }
556 }
557
558 public String toString() {
559 ThreadGroup group = getThreadGroup();
560 if (group != null) {
561 return "Thread[" + getName() + "," + getPriority() + "," +
562 group.getName() + "]";
563 } else {
564 return "Thread[" + getName() + "," + getPriority() + "," +
565 "" + "]";
566 }
567 }
568
569 //获取当前线程的ClassLoader
570 @CallerSensitive
571 public ClassLoader getContextClassLoader() {
572 if (contextClassLoader == null)
573 return null;
574 SecurityManager sm = System.getSecurityManager();
575 if (sm != null) {
576 ClassLoader.checkClassLoaderPermission(contextClassLoader,
577 Reflection.getCallerClass());
578 }
579 return contextClassLoader;
580 }
581
582 //设置当前线程的ClassLoader
583 public void setContextClassLoader(ClassLoader cl) {
584 SecurityManager sm = System.getSecurityManager();
585 if (sm != null) {
586 sm.checkPermission(new RuntimePermission("setContextClassLoader"));
587 }
588 contextClassLoader = cl;
589 }
590
591 //当且仅当当前线程持有指定对象的***锁时,返回true,用于断言:assert Thread.holdsLock(obj);
592 public static native boolean holdsLock(Object obj);
593
594 private static final StackTraceElement[] EMPTY_STACK_TRACE
595 = new StackTraceElement[0];
596
597 /*
598 返回当前线程堆栈转储的堆栈跟踪元素数组
599 如果线程没有start、已经start但没有被调度器调度或已经终止,那么数组长度为0
600 如果数组长度非0,那么数组的第一个元素(索引为0)表示栈的顶部,最后一个元素表示栈底
601 */
602 public StackTraceElement[] getStackTrace() {
603 if (this != Thread.currentThread()) {
604 SecurityManager security = System.getSecurityManager();
605 if (security != null) {
606 security.checkPermission(
607 SecurityConstants.GET_STACK_TRACE_PERMISSION);
608 }
609
610 if (!isAlive()) {
611 return EMPTY_STACK_TRACE;
612 }
613 StackTraceElement[][] stackTraceArray = dumpThreads(new Thread[]{this});
614 StackTraceElement[] stackTrace = stackTraceArray[0];
615
616 if (stackTrace == null) {
617 stackTrace = EMPTY_STACK_TRACE;
618 }
619 return stackTrace;
620 } else {
621 return (new Exception()).getStackTrace();
622 }
623 }
624
625 //返回所有存活线程的堆栈跟踪数组的map,由于getAllStackTraces时线程仍在执行,所以得到的结果仅仅是一个快照
626 public static Map<Thread, StackTraceElement[]> getAllStackTraces() {
627 SecurityManager security = System.getSecurityManager();
628 if (security != null) {
629 security.checkPermission(
630 SecurityConstants.GET_STACK_TRACE_PERMISSION);
631 security.checkPermission(
632 SecurityConstants.MODIFY_THREADGROUP_PERMISSION);
633 }
634
635 Thread[] threads = getThreads();
636 StackTraceElement[][] traces = dumpThreads(threads);
637 Map<Thread, StackTraceElement[]> m = new HashMap<>(threads.length);
638 for (int i = 0; i < threads.length; i++) {
639 StackTraceElement[] stackTrace = traces[i];
640 if (stackTrace != null) {
641 m.put(threads[i], stackTrace);
642 }
643 }
644 return m;
645 }
646
647
648 private static final RuntimePermission SUBCLASS_IMPLEMENTATION_PERMISSION =
649 new RuntimePermission("enableContextClassLoaderOverride");
650
651 //Replace with ConcurrentReferenceHashMap when/if it appears in a future release
652 private static class Caches {
653 //子类安全审核结果的缓存
654 static final ConcurrentMap<WeakClassKey, Boolean> subclassAudits =
655 new ConcurrentHashMap<>();
656
657 //审核子类的弱引用队列
658 static final ReferenceQueue<Class<?>> subclassAuditsQueue =
659 new ReferenceQueue<>();
660 }
661
662 private static boolean isCCLOverridden(Class<?> cl) {
663 if (cl == Thread.class)
664 return false;
665
666 processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);
667 WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
668 Boolean result = Caches.subclassAudits.get(key);
669 if (result == null) {
670 result = Boolean.valueOf(auditSubclass(cl));
671 Caches.subclassAudits.putIfAbsent(key, result);
672 }
673
674 return result.booleanValue();
675 }
676
677 private static boolean auditSubclass(final Class<?> subcl) {
678 Boolean result = AccessController.doPrivileged(
679 new PrivilegedAction<Boolean>() {
680 public Boolean run() {
681 for (Class<?> cl = subcl;
682 cl != Thread.class;
683 cl = cl.getSuperclass()) {
684 try {
685 cl.getDeclaredMethod("getContextClassLoader", new Class<?>[0]);
686 return Boolean.TRUE;
687 } catch (NoSuchMethodException ex) {
688 }
689 try {
690 Class<?>[] params = {ClassLoader.class};
691 cl.getDeclaredMethod("setContextClassLoader", params);
692 return Boolean.TRUE;
693 } catch (NoSuchMethodException ex) {
694 }
695 }
696 return Boolean.FALSE;
697 }
698 }
699 );
700 return result.booleanValue();
701 }
702
703 private native static StackTraceElement[][] dumpThreads(Thread[] threads);
704
705 private native static Thread[] getThreads();
706
707 /*
708 返回当前线程的tid,线程的tid是一个在线程创建时生成的long类型正数
709 线程的tid在其生命周期内不会更改且独一无二,当一个线程终止时,tid可以被重用
710 */
711 public long getId() {
712 return tid;
713 }
714
715 //任一时刻线程只能处于其中的一个状态,且只是虚拟机的状态值,并不会反映操作系统的线程状态
716 public enum State {
717 //线程没有调用start方法之前的状态
718 NEW,
719
720 //线程在JVM里面运行的状态,包括就绪和运行
721 RUNNABLE,
722
723 //线程等待监视器锁的状态
724 BLOCKED,
725
726 /*
727 一个线程等待其他线程的状态,这种等待是无限期的
728 Object.wait with no timeout
729 Thread.join with no timeout
730 LockSupport.park
731 */
732 WAITING,
733
734 /*
735 一个线程等待其他线程的状态,这种等待是有时间限制的
736 Thread.sleep
737 Object.wait with timeout
738 Thread.join with timeout
739 LockSupport.parkNanos
740 LockSupport.parkUntil
741 */
742 TIMED_WAITING,
743
744 //线程执行完毕已经退出的状态
745 TERMINATED;
746 }
747
748 //返回当前线程的状态
749 public State getState() {
750 return sun.misc.VM.toThreadState(threadStatus);
751 }
752
753 @FunctionalInterface
754 public interface UncaughtExceptionHandler {
755 void uncaughtException(Thread t, Throwable e);
756 }
757
758 private volatile UncaughtExceptionHandler uncaughtExceptionHandler;
759
760 private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;
761
762 public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
763 SecurityManager sm = System.getSecurityManager();
764 if (sm != null) {
765 sm.checkPermission(
766 new RuntimePermission("setDefaultUncaughtExceptionHandler")
767 );
768 }
769
770 defaultUncaughtExceptionHandler = eh;
771 }
772
773 public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() {
774 return defaultUncaughtExceptionHandler;
775 }
776
777 public UncaughtExceptionHandler getUncaughtExceptionHandler() {
778 return uncaughtExceptionHandler != null ?
779 uncaughtExceptionHandler : group;
780 }
781
782 public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
783 checkAccess();
784 uncaughtExceptionHandler = eh;
785 }
786
787 private void dispatchUncaughtException(Throwable e) {
788 getUncaughtExceptionHandler().uncaughtException(this, e);
789 }
790
791 static void processQueue(ReferenceQueue<Class<?>> queue,
792 ConcurrentMap<? extends
793 WeakReference<Class<?>>, ?> map) {
794 Reference<? extends Class<?>> ref;
795 while ((ref = queue.poll()) != null) {
796 map.remove(ref);
797 }
798 }
799
800 static class WeakClassKey extends WeakReference<Class<?>> {
801 private final int hash;
802
803 WeakClassKey(Class<?> cl, ReferenceQueue<Class<?>> refQueue) {
804 super(cl, refQueue);
805 hash = System.identityHashCode(cl);
806 }
807
808 @Override
809 public int hashCode() {
810 return hash;
811 }
812
813 @Override
814 public boolean equals(Object obj) {
815 if (obj == this)
816 return true;
817
818 if (obj instanceof WeakClassKey) {
819 Object referent = get();
820 return (referent != null) &&
821 (referent == ((WeakClassKey) obj).get());
822 } else {
823 return false;
824 }
825 }
826 }
827
828 @sun.misc.Contended("tlr")
829 long threadLocalRandomSeed;
830
831 @sun.misc.Contended("tlr")
832 int threadLocalRandomProbe;
833
834 @sun.misc.Contended("tlr")
835 int threadLocalRandomSecondarySeed;
836
837 private native void setPriority0(int newPriority);
838
839 private native void stop0(Object o);
840
841 private native void suspend0();
842
843 private native void resume0();
844
845 private native void interrupt0();
846
847 private native void setNativeName(String name);
848
849 }