日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JDK源码解析之 java.lang.Throwable

發(fā)布時間:2025/3/8 编程问答 56 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JDK源码解析之 java.lang.Throwable 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

在 Java 中,所有的異常都有一個共同的祖先 Throwable(可拋出)。Throwable 指定代碼中可用異常傳播機制通過 Java 應(yīng)用程序傳輸?shù)娜魏螁栴}的共性。

一、類定義

public class Throwable implements Serializable {}
  • Serializable:可被序列化的標志接口

二、成員變量

//靜態(tài)變量 //這兩個變量主要用于序列化 private static class SentinelHolder {public static final StackTraceElement STACK_TRACE_ELEMENT_SENTINEL =new StackTraceElement("", "", null, Integer.MIN_VALUE);public static final StackTraceElement[] STACK_TRACE_SENTINEL =new StackTraceElement[] {STACK_TRACE_ELEMENT_SENTINEL}; } //一個空的StackTraceElement[]數(shù)組,用來初始化或者作為返回值。 private static final StackTraceElement[] UNASSIGNED_STACK = new StackTraceElement[0]; //一個空的只讀List,同樣用于初始化 private static final List<Throwable> SUPPRESSED_SENTINEL =Collections.unmodifiableList(new ArrayList<Throwable>(0)); //前兩個用于作為錯誤信息,后兩個作為printStackTrace方法的說明前綴使用 private static final String NULL_CAUSE_MESSAGE = "Cannot suppress a null exception."; private static final String SELF_SUPPRESSION_MESSAGE = "Self-suppression not permitted"; private static final String CAUSE_CAPTION = "Caused by: "; private static final String SUPPRESSED_CAPTION = "Suppressed: "; //用作getSuppressed方法的返回值(當(dāng)suppressedExceptions沒有元素時) private static final Throwable[] EMPTY_THROWABLE_ARRAY = new Throwable[0];//實例變量 //用來保存棧信息的軌跡 private transient Object backtrace; //描述這個異常的信息 private String detailMessage; //描述這個異常由哪個Throwable導(dǎo)致,默認是this。 private Throwable cause = this; //異常拋出位置的棧信息,每個StackTraceElement代表一個棧信息,默認指向靜態(tài)常量UNASSIGNED_STACK,代表棧信息為空。 private StackTraceElement[] stackTrace = UNASSIGNED_STACK; //JDK 1.7引入的新特性。該List用來保存被屏蔽的異常對象,在try-catch語句中,如果try中拋出了異常,在執(zhí)行流程轉(zhuǎn)移到方法棧上一層之前,finally語句塊會執(zhí)行,但是,如果在finally語句塊中又拋出了一個異常,那么這個異常會覆蓋掉之前拋出的異常,這點很像finally中return的覆蓋。 private List<Throwable> suppressedExceptions = SUPPRESSED_SENTINEL;

三、構(gòu)造方法

public Throwable() {fillInStackTrace(); } /*** @param message 異常描述信息,該參數(shù)直接賦值給實例變量detailMessage*/ public Throwable(String message) {fillInStackTrace();detailMessage = message; } /*** @param message 異常描述信息,該參數(shù)直接賦值給實例變量detailMessage* @param cause 描述當(dāng)前異常由哪個異常引發(fā)*/ public Throwable(String message, Throwable cause) {fillInStackTrace();detailMessage = message;this.cause = cause; } /*** @param cause 描述當(dāng)前異常由哪個異常引發(fā)*/ public Throwable(Throwable cause) {fillInStackTrace();detailMessage = (cause==null ? null : cause.toString());this.cause = cause; } /*** @param message 異常描述信息,該參數(shù)直接賦值給實例變量detailMessage* @param cause 描述當(dāng)前異常由哪個異常引發(fā)* @param enableSuppression 是否支持Suppress異常消息* @param writableStackTrace 是否調(diào)用fillInStackTrace使堆棧信息可以寫入*/ protected Throwable(String message, Throwable cause,boolean enableSuppression, boolean writableStackTrace) {if (writableStackTrace) {fillInStackTrace();} else {stackTrace = null;}detailMessage = message;this.cause = cause;if (!enableSuppression)suppressedExceptions = null; }

Throwable提供了4個public構(gòu)造器和1個protected構(gòu)造器(該構(gòu)造器由JDK1.7引入)。4個public構(gòu)造器共同點就是都調(diào)用了fillInStackTrace方法。

fillInStackTrace會首先判斷stackTrace是不是為null,如果不為null則會調(diào)用native方法fillInStackTrace獲取當(dāng)前堆棧信息。那么什么時候為null呢,答案是上面的protected構(gòu)造器可以指定writableStackTrace為false,這樣stackTrace就為null了,就不會調(diào)用fillInStackTrace獲取堆棧信息。如果你不需要異常的棧信息,你也可以重寫這個方法,讓它直接返回this,畢竟異常的爬棧是一個開銷比較大的操作。

四、常用方法

1、printStackTrace方法

printStackTrace把傳入的輸入流用內(nèi)部類WrappedPrintStream或WrappedPrintWriter包裝,主要用來實現(xiàn)printStackTrace方法在打印堆棧信息時的線程安全。

public void printStackTrace() {printStackTrace(System.err); }public void printStackTrace(PrintStream s) {printStackTrace(new WrappedPrintStream(s)); }public void printStackTrace(PrintWriter s) {printStackTrace(new WrappedPrintWriter(s)); }private void printStackTrace(PrintStreamOrWriter s) {Set<Throwable> dejaVu = Collections.newSetFromMap(new IdentityHashMap<Throwable, Boolean>());dejaVu.add(this);synchronized (s.lock()) {s.println(this);StackTraceElement[] trace = getOurStackTrace();for (StackTraceElement traceElement : trace)s.println("\tat " + traceElement);for (Throwable se : getSuppressed())se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu);Throwable ourCause = getCause();if (ourCause != null)ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu);} } }

printStackTrace把傳入的輸入流用內(nèi)部類WrappedPrintStream或WrappedPrintWriter包裝,主要用來實現(xiàn)printStackTrace方法在打印堆棧信息時的線程安全。

2、getMessage()和getLocalizedMessage()

默認條件下可以調(diào)用getMessage或getLocalizedMessage方法獲取detailMessage

public String getMessage() {return detailMessage; } public String getLocalizedMessage() {return getMessage(); }

3、getCause()和initCause()

通過構(gòu)造器自定義cause。構(gòu)造完成后,可以通過getCause方法訪問獲取,如果沒有指定cause,則返回null。

在構(gòu)造完成后,也可通過initCause方法修改:修改cause的前提是必須在構(gòu)造方法中沒有指定別的cause(即默認條件下cause為this),否則會拋出IllegalStateException異常。另外也不能修改cause為this。

public synchronized Throwable getCause() {return (cause == this ? null : cause); }public synchronized Throwable initCause(Throwable cause) {if (this.cause != this)throw new IllegalStateException("Can't overwrite cause with " +Objects.toString(cause, "a null"), this);if (cause == this)throw new IllegalArgumentException("Self-causation not permitted", this);this.cause = cause;return this; }

五、拓展

1.處理異常機制

在 Java 應(yīng)用程序中,異常處理機制為:拋出異常,捕捉異常。

拋出異常:當(dāng)一個方法出現(xiàn)錯誤引發(fā)異常時,方法創(chuàng)建異常對象并交付運行時系統(tǒng),異常對象中包含了異常類型和異常出現(xiàn)時的程序狀態(tài)等異常信息。運行時系統(tǒng)負責(zé)尋找處置異常的代碼并執(zhí)行。throwsthrow

? 捕獲異常:在方法拋出異常之后,運行時系統(tǒng)將轉(zhuǎn)為尋找合適的異常處理器(exception handler)。潛在的異常處理器是異常發(fā)生時依次存留在調(diào)用棧中的方法的集合。當(dāng)異常處理器所能處理的異常類型與方法拋出的異常類型相符時,即為合適 的異常處理器。運行時系統(tǒng)從發(fā)生異常的方法開始,依次回查調(diào)用棧中的方法,直至找到含有合適異常處理器的方法并執(zhí)行。當(dāng)運行時系統(tǒng)遍歷調(diào)用棧而未找到合適 的異常處理器,則運行時系統(tǒng)終止。同時,意味著Java程序的終止。try…catch

? 對于運行時異常、錯誤或可查異常,Java技術(shù)所要求的異常處理方式有所不同。

? 由于運行時異常的不可查性,為了更合理、更容易地實現(xiàn)應(yīng)用程序,Java規(guī)定,運行時異常將由Java運行時系統(tǒng)自動拋出,允許應(yīng)用程序忽略運行時異常。

? 對于方法運行中可能出現(xiàn)的Error,當(dāng)運行方法不欲捕捉時,Java允許該方法不做任何拋出聲明。因為,大多數(shù)Error異常屬于永遠不能被允許發(fā)生的狀況,也屬于合理的應(yīng)用程序不該捕捉的異常。

? 對于所有的可查異常,Java規(guī)定:一個方法必須捕捉,或者聲明拋出方法之外。也就是說,當(dāng)一個方法選擇不捕捉可查異常時,它必須聲明將拋出異常。

? 能夠捕捉異常的方法,需要提供相符類型的異常處理器。所捕捉的異常,可能是由于自身語句所引發(fā)并拋出的異常,也可能是由某個調(diào)用的方法或者Java運行時 系統(tǒng)等拋出的異常。也就是說,一個方法所能捕捉的異常,一定是Java代碼在某處所拋出的異常。簡單地說,異常總是先被拋出,后被捕捉的。

? 任何Java代碼都可以拋出異常,如:自己編寫的代碼、來自Java開發(fā)環(huán)境包中代碼,或者Java運行時系統(tǒng)。無論是誰,都可以通過Java的throw語句拋出異常。

? 從方法中拋出的任何異常都必須使用throws子句。

? 捕捉異常通過try-catch語句或者try-catch-finally語句實現(xiàn)。

? 總體來說,Java規(guī)定:對于可查異常必須捕捉、或者聲明拋出。允許忽略不可查的RuntimeException和Error。

try { // 可能會發(fā)生異常的程序代碼 } catch (Type1 id1){ // 捕獲并處置try拋出的異常類型Type1 } catch (Type2 id2){ //捕獲并處置try拋出的異常類型Type2 }

總結(jié)

以上是生活随笔為你收集整理的JDK源码解析之 java.lang.Throwable的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。