JDK源碼分析系列_Thread


  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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM