1、Thread類實現了Runnable的接口
public class Thread implements Runnable
Runnable的源碼只有一個抽象的run方法,並被註解@FunctionalInterface 定義了函數式接口,它們主要用在Lambda表達式和方法引用,使用Lambda時必須是函數式接口,這就是使用lambda表達式創建線程的方式,簡化了代碼
new Thread(() -> System.out.println("lambda表達式")).start();
2、初始化
/* Make sure registerNatives is the first thing <clinit> does.
確保registerNatives是所做的第一件事。*/
private static native void registerNatives();
static {
registerNatives();
}
從上面的代碼中看到定義了一個靜態初始化塊,我們知道當創建Java對象時,系統總是先調用靜態初始化塊
在上面的靜態初始化塊中調用了registerNatives()方法,並且使用了private來修飾,表面這個方法是私有的並不被外部調用。
在Java中使用native關鍵字修飾的方法,說明此方法並不是由Java中完成的,而是通過C/C++來完成的,並被編譯成.dll,之後才由Java調用。方法的具體實現是在dll文件中,當然對於不同平臺實現的細節也有所不同,以上registerNatives()方法主要作用就是將C/C++中的方法映射到Java中的native方法,實現方法命名的解耦這篇解釋的原文鏈接:https://blog.csdn.net/liudaohonglk/article/details/78278368
3、屬性
private volatile String name; // 線程名字
private int priority; // 優先級
private Thread threadQ;
private long eetop;
/* Whether or not to single_step this thread. */
//是否是單步執行
private boolean single_step;
/* Whether or not the thread is a daemon thread. */
//是否是守護線程
private boolean daemon = false;
/* JVM state */
// 虛擬機狀態
private boolean stillborn = false;
/* What will be run. */
//將會被執行的Runnable.使用Runnabke方式創建線程時所用
private Runnable target;
/* The group of this thread */
//線程分組
private ThreadGroup group;
/* The context ClassLoader for this thread */
//這個線程的上下文
private ClassLoader contextClassLoader;
/* The inherited AccessControlContext of this thread */
//繼承的請求控制
private AccessControlContext inheritedAccessControlContext;
/* For autonumbering anonymous threads. */
//默認線程的自動編號
private static int threadInitNumber;
private static synchronized int nextThreadNum() {
return threadInitNumber++;
}
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
// 用於修飾或說明這個線程ThreadLocal值。這個map是由ThreadLocal類
ThreadLocal.ThreadLocalMap threadLocals = null;
/*
* InheritableThreadLocal values pertaining to this thread. This map is
* maintained by the InheritableThreadLocal class.
*/
//InheritableThreadLocal值屬於該線程。這張地圖是由InheritableThreadLocal類維護
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
/*
* The requested stack size for this thread, or 0 if the creator did
* not specify a stack size. It is up to the VM to do whatever it
* likes with this number; some VMs will ignore it.
*/
//該線程請求的堆棧大小 默認一般都是忽略
private long stackSize;
/*
* JVM-private state that persists after native thread termination.
*/
//JVM-private原生線程終止後持續狀態
private long nativeParkEventPointer;
/*
* Thread ID
*/
//每個線程都有專屬ID,但名字可能重複
private long tid;
/* For generating thread ID */
//用來生成thread ID
private static long threadSeqNumber;
/* Java thread status for tools,
* initialized to indicate thread 'not yet started'
*/
//標識線程狀態,默認是線程未啓動
private volatile int threadStatus = 0;
//得到下個thread ID
private static synchronized long nextThreadID() {
return ++threadSeqNumber;
}
/**
* The argument supplied to the current call to
* java.util.concurrent.locks.LockSupport.park.
* Set by (private) java.util.concurrent.locks.LockSupport.setBlocker
* Accessed using java.util.concurrent.locks.LockSupport.getBlocker
*/
//中斷阻塞器:當線程發生IO中斷時,需要在線程被設置爲中斷狀態後調用該對象的interrupt方法
volatile Object parkBlocker;
/* The object in which this thread is blocked in an interruptible I/O
* operation, if any. The blocker's interrupt method should be invoked
* after setting this thread's interrupt status.
*/
//阻塞器鎖,主要用於處理阻塞情況
private volatile Interruptible blocker;
private final Object blockerLock = new Object();
/* Set the blocker field; invoked via sun.misc.SharedSecrets from java.nio code
*/
//阻斷鎖
void blockedOn(Interruptible b) {
synchronized (blockerLock) {
blocker = b;
}
}
/**
* The minimum priority that a thread can have.
*/
//線程的優先級中最小的
public final static int MIN_PRIORITY = 1;
/**
* The default priority that is assigned to a thread.
*/
//線程的優先級中第二的同時也是默認的優先級
public final static int NORM_PRIORITY = 5;
/**
* The maximum priority that a thread can have.
*/
//最高的優先級
public final static int MAX_PRIORITY = 10;
4、native方法(非java應用)
//獲得當前的線程
public static native Thread currentThread();
//禮讓線程,會放棄當前的運行狀態變爲就緒狀態去重新競爭執行
public static native void yield();
//休眠,讓線程停止多少時間再次執行
public static native void sleep(long millis) throws InterruptedException;
//開始線程
private native void start0();
//調用該方法的對象所表示的那個線程的isInterrupted(),不會重置當前線程的中斷狀態
private native boolean isInterrupted(boolean ClearInterrupted);
//判斷線程是否存活
public final native boolean isAlive();
//@Deprecated註解的意思是不推薦使用,就不解釋意思了
@Deprecated
public native int countStackFrames();
//當且僅當當前線程在指定的對象上保持監視器鎖時,才返回 true。
public static native boolean holdsLock(Object obj);
//設置線程優先級
private native void setPriority0(int newPriority);
//停止線程
private native void stop0(Object o);
//線程掛起(暫停)
private native void suspend0();
//將一個掛起線程復活繼續執行
private native void resume0();
//該線程的中斷狀態將被設置
private native void interrupt0();
//沒找到解釋,字面意思是寫入native的名稱
private native void setNativeName(String name);
5、Thread的構造方法
//默認的什麼都不傳
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
//target被調用RUN方法的目標對象
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
//設置了線程分組並傳遞了被調用RUN方法的目標對象
public Thread(ThreadGroup group, Runnable target) {
init(group, target, "Thread-" + nextThreadNum(), 0);
}
//只設置了線程名稱
public Thread(String name) {
init(null, null, name, 0);
}
//設置了線程分組和線程名稱
public Thread(ThreadGroup group, String name) {
init(group, null, name, 0);
}
//傳遞了調用RUN方法的目標對象並設置了線程名稱
public Thread(Runnable target, String name) {
init(null, target, name, 0);
}
//傳遞了調用RUN方法的目標對象並設置了線程分組和線程名稱
public Thread(ThreadGroup group, Runnable target, String name) {
init(group, target, name, 0);
}
//傳遞了調用RUN方法的目標對象並設置了線程分組和線程名稱和堆棧大小
public Thread(ThreadGroup group, Runnable target, String name,
long stackSize) {
init(group, target, name, stackSize);
}
6、普通方法
//millis爲毫秒,nanos爲納秒,1000納秒=1毫秒,其他跟sleep方法一樣
public static void sleep(long millis, int nanos)
throws InterruptedException {
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
millis++;
}
sleep(millis);
}
//init初始化,線程的初始化方法,g = 分組 target = 調用run的對象 name = 線程名稱 stackSize = 設置的堆棧大小
private void init(ThreadGroup g, Runnable target, String name,
long stackSize) {
init(g, target, name, stackSize, null, true);
}
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc,
boolean inheritThreadLocals) {
//如果線程名稱爲空
if (name == null) {
throw new NullPointerException("name cannot be null");
}
//設置volatile的name爲傳遞name
this.name = name;
//獲得當前線程
Thread parent = currentThread();
//獲得系統的安全管理器
SecurityManager security = System.getSecurityManager();
if (g == null) {
//安全檢查
if (security != null) {
g = security.getThreadGroup();
}
//設置線程組
if (g == null) {
g = parent.getThreadGroup();
}
}
//檢查是否允許調用線程修改線程組參數
g.checkAccess();
//是否有權限訪問
if (security != null) {
if (isCCLOverridden(getClass())) {
security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
}
//往線程組添加線程但未啓動
g.addUnstarted();
//線程組
this.group = g;
//是否守護線程
this.daemon = parent.isDaemon();
//優先級
this.priority = parent.getPriority();
//每個線程都有一個優先級,高優先級線程的執行優先於低優先級線程。每個線程都可以或不可以標記爲一個守護程序。當某個線程中運行的代碼創建一個新 Thread 對象時,該新線程的初始優先級被設定爲創建線程的優先級,並且當且僅當創建線程是守護線程時,新線程纔是守護程序。
if (security == null || isCCLOverridden(parent.getClass()))
this.contextClassLoader = parent.getContextClassLoader();
else
this.contextClassLoader = parent.contextClassLoader;
this.inheritedAccessControlContext =
acc != null ? acc : AccessController.getContext();
this.target = target;
setPriority(priority);
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
/* Stash the specified stack size in case the VM cares */
this.stackSize = stackSize;
/* Set thread ID */
tid = nextThreadID();
}
//克隆。構造一個新線程。
@Override
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
//使線程進入可執行(runnable狀態)的狀態
public synchronized void start() {
//驗證線程的狀態,如果線程已啓動則拋異常
if (threadStatus != 0)
throw new IllegalThreadStateException();
//向線程組裏添加此線程
group.add(this);
boolean started = false;
try {
//使線程進入可執行(runnable狀態)的狀態
start0();
//設置狀態爲true
started = true;
} finally {
try {
//如果狀態不爲true,此線程啓動失敗
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
//使線程從可運行狀態轉化爲運行狀態
@Override
public void run() {
if (target != null) {
target.run();
}
}
//這個方法是在Run方法執行結束後用於結束線程的。通過單步調試一個線程發現執行完run方法之後會進入exit方法。
private void exit() {
if (group != null) {
group.threadTerminated(this);
group = null;
}
/* Aggressively null out all reference fields: see bug 4006245 */
target = null;
/* Speed the release of some of these resources */
threadLocals = null;
inheritableThreadLocals = null;
inheritedAccessControlContext = null;
blocker = null;
uncaughtExceptionHandler = null;
}
//@Deprecated不建議使用
//停止線程
@Deprecated
public final void stop() {
SecurityManager security = System.getSecurityManager();
//如果安全管理器不爲空
if (security != null) {
//檢查是否允許調用線程修改線程組參數
checkAccess();
//如果這個線程不是當前線程或者這個線程以銷燬
if (this != Thread.currentThread()) {
//如果所請求的訪問,通過給定的權限,指定的安全策略不允許根據當前有效的方法將拋出一個SecurityException。
security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
}
}
//如果線程已啓動
if (threadStatus != 0) {
//如果線程被掛起則喚醒
resume();
}
//停止線程
stop0(new ThreadDeath());
}
//@Deprecated不建議使用
//停止線程
@Deprecated
public final synchronized void stop(Throwable obj) {
throw new UnsupportedOperationException();
}
//中斷此線程(阻塞)但實際上只是給線程設置一箇中斷標誌,線程仍會繼續運行。
public void interrupt() {
if (this != Thread.currentThread())
checkAccess();
synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) {
interrupt0(); // Just to set the interrupt flag
b.interrupt(this);
return;
}
}
interrupt0();
}
//測試當前線程是否被中斷(檢查中斷標誌),返回一個boolean並清除中斷狀態,第二次再調用時中斷狀態已經被清除,將返回一個false。
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
//只測試此線程是否被中斷 ,不清除中斷狀態。
public boolean isInterrupted() {
return isInterrupted(false);
}
private native boolean isInterrupted(boolean ClearInterrupted);
//@Deprecated不建議使用
//銷燬線程組及其所有子組。 線程組必須爲空,表示線程組中的所有線程都已停止。
@Deprecated
public void destroy() {
throw new NoSuchMethodError();
}
//@Deprecated不建議使用
//暫停線程直到被喚醒 而Abort強制殺死線程
@Deprecated
public final void suspend() {
checkAccess();
suspend0();
}
//@Deprecated不建議使用
//如果線程被掛起則喚醒
@Deprecated
public final void resume() {
checkAccess();
resume0();
}
//設置線程的優先級
public final void setPriority(int newPriority) {
ThreadGroup g;
//檢查是否允許調用線程修改線程組參數
checkAccess();
//如果設置的優先級大於最大優先級或者小於最小的優先級拋異常
if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
throw new IllegalArgumentException();
}
if((g = getThreadGroup()) != null) {
if (newPriority > g.getMaxPriority()) {
newPriority = g.getMaxPriority();
}
setPriority0(priority = newPriority);
}
}
//獲得線程的優先級
public final int getPriority() {
return priority;
}
//設置線程名稱
public final synchronized void setName(String name) {
checkAccess();
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name;
if (threadStatus != 0) {
setNativeName(name);
}
}
//獲取線程名稱
public final String getName() {
return name;
}
//獲得當前的線程的線程組
public final ThreadGroup getThreadGroup() {
return group;
}
//獲得當前線程組中還在活動中的線程數
public static int activeCount() {
return currentThread().getThreadGroup().activeCount();
}
//將這個線程組中存活的線程全部複製到預設置好的數組中
public static int enumerate(Thread tarray[]) {
return currentThread().getThreadGroup().enumerate(tarray);
}
//@Deprecated不建議使用
@Deprecated
public native int countStackFrames();
//堵塞當前線程,使其處於等待狀態,因爲子線程執行的時間可能比主線程執行時間還長,所以join是主線程需要在它執行完後再銷燬。當然也可以加參數join(long millis, int nanos),使其等待N秒N毫秒,如果它已經處於join方法,則報InterruptedException 。
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
public final synchronized void join(long millis, int nanos)
throws InterruptedException {
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
millis++;
}
join(millis);
}
public final void join() throws InterruptedException {
join(0);
}
//將當前線程的堆棧跟蹤打印至標準錯誤流
public static void dumpStack() {
new Exception("Stack trace").printStackTrace();
}
/設置線程爲守護線程
public final void setDaemon(boolean on) {
//檢查是否允許調用線程修改線程組參數
checkAccess();
//首先先去確認此線程是否處於活動狀態,如果處於活動狀態則拋異常
if (isAlive()) {
throw new IllegalThreadStateException();
}
//將其設置爲守護線程
daemon = on;
}
//確認線程是否是守護線程
public final boolean isDaemon() {
return daemon;
}
//檢查是否允許調用線程修改線程組參數
public final void checkAccess() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkAccess(this);
}
}
////返回該線程的字符串表示形式,包括線程名稱、優先級和線程組。
public String toString() {
ThreadGroup group = getThreadGroup();
if (group != null) {
return "Thread[" + getName() + "," + getPriority() + "," +
group.getName() + "]";
} else {
return "Thread[" + getName() + "," + getPriority() + "," +
"" + "]";
}
}
//@CallerSensitive註解:jdk內有些方法,jvm的開發者認爲這些方法危險,不希望開發者調用,就把這種危險的方法用@CallerSensitive修飾,並在“jvm”級別檢查。
//返回該線程的上下文 ClassLoader。上下文 ClassLoader 由線程創建者提供,供運行於該線程中的代碼在加載類和資源時使用。如果未設定,則默認爲父線程的 ClassLoader 上下文。原始線程的上下文 ClassLoader 通常設定爲用於加載應用程序的類加載器。
//首先,如果有安全管理器,並且調用者的類加載器不是 null,也不同於其上下文類加載器正在被請求的線程上下文類加載器的祖先,則通過 RuntimePermission("getClassLoader") 權限調用該安全管理器的 checkPermission 方法,查看是否可以獲取上下文 ClassLoader。
@CallerSensitive
public ClassLoader getContextClassLoader() {
if (contextClassLoader == null)
return null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
ClassLoader.checkClassLoaderPermission(contextClassLoader,
Reflection.getCallerClass());
}
return contextClassLoader;
}
//設置該線程的上下文 ClassLoader。上下文 ClassLoader 可以在創建線程設置,並允許創建者在加載類和資源時向該線程中運行的代碼提供適當的類加載器。
//首先,如果有安全管理器,則通過 RuntimePermission("setContextClassLoader") 權限調用其 checkPermission 方法,查看是否可以設置上下文 ClassLoader。
public void setContextClassLoader(ClassLoader cl) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("setContextClassLoader"));
}
contextClassLoader = cl;
}
// 返回一個表示該線程堆棧轉儲的堆棧跟蹤元素數組。
public StackTraceElement[] getStackTrace() {
if (this != Thread.currentThread()) {
// check for getStackTrace permission
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPermission(
SecurityConstants.GET_STACK_TRACE_PERMISSION);
}
// optimization so we do not call into the vm for threads that
// have not yet started or have terminated
if (!isAlive()) {
return EMPTY_STACK_TRACE;
}
StackTraceElement[][] stackTraceArray = dumpThreads(new Thread[] {this});
StackTraceElement[] stackTrace = stackTraceArray[0];
// a thread that was alive during the previous isAlive call may have
// since terminated, therefore not having a stacktrace.
if (stackTrace == null) {
stackTrace = EMPTY_STACK_TRACE;
}
return stackTrace;
} else {
// Don't need JVM help for current thread
return (new Exception()).getStackTrace();
}
}
//返回所有活動線程的堆棧跟蹤的一個映射。
public static Map<Thread, StackTraceElement[]> getAllStackTraces() {
// check for getStackTrace permission
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPermission(
SecurityConstants.GET_STACK_TRACE_PERMISSION);
security.checkPermission(
SecurityConstants.MODIFY_THREADGROUP_PERMISSION);
}
// Get a snapshot of the list of all threads
Thread[] threads = getThreads();
StackTraceElement[][] traces = dumpThreads(threads);
Map<Thread, StackTraceElement[]> m = new HashMap<>(threads.length);
for (int i = 0; i < threads.length; i++) {
StackTraceElement[] stackTrace = traces[i];
if (stackTrace != null) {
m.put(threads[i], stackTrace);
}
// else terminated so we don't put it in the map
}
return m;
}
//安全審計結果緩存的子類
//將來的版本中替換爲ConcurrentReferenceHashMap
private static class Caches {
/** cache of subclass security audit results */
static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits =
new ConcurrentHashMap<>();
/** queue for WeakReferences to audited subclasses */
static final ReferenceQueue<Class<?>> subclassAuditsQueue =
new ReferenceQueue<>();
}
//驗證這個子類實例是否可以被構造,在不違反安全約束:子類不能覆蓋
private static boolean isCCLOverridden(Class<?> cl) {
if (cl == Thread.class)
return false;
processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);
WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
Boolean result = Caches.subclassAudits.get(key);
if (result == null) {
result = Boolean.valueOf(auditSubclass(cl));
Caches.subclassAudits.putIfAbsent(key, result);
}
return result.booleanValue();
}
//對給定的子類執行反射檢查以驗證它不是覆蓋安全敏感的非final方法,如果子類重寫任何方法,返回true否則返回false
private static boolean auditSubclass(final Class<?> subcl) {
Boolean result = AccessController.doPrivileged(
new PrivilegedAction<Boolean>() {
public Boolean run() {
for (Class<?> cl = subcl;
cl != Thread.class;
cl = cl.getSuperclass())
{
try {
cl.getDeclaredMethod("getContextClassLoader", new Class<?>[0]);
return Boolean.TRUE;
} catch (NoSuchMethodException ex) {
}
try {
Class<?>[] params = {ClassLoader.class};
cl.getDeclaredMethod("setContextClassLoader", params);
return Boolean.TRUE;
} catch (NoSuchMethodException ex) {
}
}
return Boolean.FALSE;
}
}
);
return result.booleanValue();
}
//獲取線程ID
public long getId() {
return tid;
}
//枚舉,線程狀態
public enum State {
//新建(new)
NEW,
//可運行(Runnable)
RUNNABLE,
//阻塞(block)
BLOCKED,
//無限期等待(waiting)
WAITING,
//限期等待(TIMED_WAITING)
TIMED_WAITING,
//結束(terminated)
TERMINATED;
}
調用線程的start()方法,線程進入可運行狀態(Runnable)
Java線程中的Runnable狀態包括操作系統線程的running和ready狀態,處於就緒狀態的線程一旦獲得CPU使用權,進入運行狀態
即處於Runnable狀態的線程可能正在運行,也可能正在等待CPU分配時間片
調用Thread類的start()方法之後
一個線程處於等待(waiting)狀態,表示該線程正在等待其它線程執行特定的操作
例如,一個線程調用了Object類的空參的wait方法,表示該線程等待其它線程調用該對象的notify或者notifyAll方法
一個線程調用了Thread類的空參的join方法,表示該線程在等待一個特定的線程終止
何時進入waiting狀態:
調用Object類空參的wait()
調用Thread類空參的join()
一個線程在執行過程中,想獲得某一資源的鎖,但是該資源又被其它線程佔用,此時,當前線程處於阻塞狀態(例如,進入一個同步方法或者同步代碼塊,要先獲得鎖)
阻塞和等待的不同是,阻塞狀態是在等待一個排它鎖
等待狀態實在等待一個事件的發生,如等待時間到,喚醒方法被調用
一個線程處於超時等待狀態(timed_waiting),和waiting不同的是,將在特定的時間內自行返回
何時進入timed_waiting狀態:
調用Object類有參的wait()
調用Thread類有參的join()
調用Thread類的sleep方法(sleep方法沒有空參的重載形式)
一個線程執行完畢,進入終止狀態(terminated)
線程執行完畢
線程在執行過程中拋出異常
//獲取線程狀態
public State getState() {
// get current thread state
return sun.misc.VM.toThreadState(threadStatus);
}
//@FunctionalInterface 函數式接口
//記錄錯誤日誌,即對未知異常的處理
@FunctionalInterface
public interface UncaughtExceptionHandler {
/**
* Method invoked when the given thread terminates due to the
* given uncaught exception.
* <p>Any exception thrown by this method will be ignored by the
* Java Virtual Machine.
* @param t the thread
* @param e the exception
*/
void uncaughtException(Thread t, Throwable e);
}
//某段代碼做try … catch 沒有catch到的代碼,發生異常的時候,就會由它來處理。
public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(
new RuntimePermission("setDefaultUncaughtExceptionHandler")
);
}
defaultUncaughtExceptionHandler = eh;
}
//獲取異常信息
public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler(){
return defaultUncaughtExceptionHandler;
}
//查詢線程的UncaughtExceptionHandler並將線程和異常作爲參數傳遞給handler的uncaughtException()方法進行處理。
public UncaughtExceptionHandler getUncaughtExceptionHandler() {
return uncaughtExceptionHandler != null ?
uncaughtExceptionHandler : group;
}
//存入UncaughtExceptionHandler信息
public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
checkAccess();
uncaughtExceptionHandler = eh;
}
//線程出現未捕獲異常後,JVM將調用Thread中的dispatchUncaughtException方法把異常傳遞給線程的未捕獲異常處理器。
private void dispatchUncaughtException(Throwable e) {
getUncaughtExceptionHandler().uncaughtException(this, e);
}
//從指定的映射中移除指定引用隊列中已排隊的任何鍵
static void processQueue(ReferenceQueue<Class<?>> queue,
ConcurrentMap<? extends
WeakReference<Class<?>>, ?> map)
{
Reference<? extends Class<?>> ref;
while((ref = queue.poll()) != null) {
map.remove(ref);
}
}
//類對象的弱鍵
static class WeakClassKey extends WeakReference<Class<?>> {
/**
* saved value of the referent's identity hash code, to maintain
* a consistent hash code after the referent has been cleared
*/
private final int hash;
/**
* Create a new WeakClassKey to the given object, registered
* with a queue.
*/
WeakClassKey(Class<?> cl, ReferenceQueue<Class<?>> refQueue) {
super(cl, refQueue);
hash = System.identityHashCode(cl);
}
/**
* Returns the identity hash code of the original referent.
*/
@Override
public int hashCode() {
return hash;
}
/**
* Returns true if the given object is this identical
* WeakClassKey instance, or, if this object's referent has not
* been cleared, if the given object is another WeakClassKey
* instance with the identical non-null referent as this one.
*/
@Override
public boolean equals(Object obj) {
if (obj == this)
return true;
if (obj instanceof WeakClassKey) {
Object referent = get();
return (referent != null) &&
(referent == ((WeakClassKey) obj).get());
} else {
return false;
}
}
}