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 }