package java.lang;
import java.io.*;
/**
*
* Throwable是所有Error和Exceptiong的父類
* 注意它有四個建構函式:
* Throwable()
* Throwable(String message)
* Throwable(Throwable cause)
* Throwable(String message, Throwable cause)
*
* comment by liqiang
*
*/
public class Throwable implements Serializable {
private static final long serialVersionUID = -3042686055658047285L;
/**
* Native code saves some indication of the stack backtrace in this slot.
*/
private transient Object backtrace;
/**
*
* 描述此異常的資訊
*
*/
private String detailMessage;
/**
*
* 表示當前異常由那個Throwable引起
* 如果為null表示此異常不是由其他Throwable引起的
* 如果此對象與自己相同,表明此異常的起因對象還沒有別初始化
*
*/
private Throwable cause = this;
/**
*
* 描述異常軌跡的數組
*
*/
private StackTraceElement[] stackTrace;
/**
*
* 建構函式,起因對象沒有被初始化可以在以後使用initCause進行初始化
* fillInStackTrace可以用來初始化它的異常軌跡的數組
*
*/
public Throwable() {
fillInStackTrace();
}
/**
*
* 建構函式
*
*/
public Throwable(String message) {
//填充異常軌跡數組
fillInStackTrace();
//初始化異常描述資訊
detailMessage = message;
}
/**
*
* 建構函式,cause表示起因對象
*
*/
public Throwable(String message, Throwable cause) {
fillInStackTrace();
detailMessage = message;
this.cause = cause;
}
/**
*
* 建構函式
*
*/
public Throwable(Throwable cause) {
fillInStackTrace();
detailMessage = (cause==null ? null : cause.toString());
this.cause = cause;
}
/**
*
* 擷取詳細資料
*
*/
public String getMessage() {
return detailMessage;
}
/**
*
* 擷取詳細資料
*
*/
public String getLocalizedMessage() {
return getMessage();
}
/**
*
* 擷取起因對象
*
*/
public Throwable getCause() {
return (cause==this ? null : cause);
}
/**
*
* 初始化起因對象,這個方法只能在未被初始化的情況下調用一次
*
*/
public synchronized Throwable initCause(Throwable cause) {
//如果不是未初始化狀態則拋出異常
if (this.cause != this)
throw new IllegalStateException("Can't overwrite cause");
//要設定的起因對象與自身相等則拋出異常
if (cause == this)
throw new IllegalArgumentException("Self-causation not permitted");
//設定起因對象
this.cause = cause;
//返回設定的起因的對象
return this;
}
/**
*
* 字串表示形式
*
*/
public String toString() {
String s = getClass().getName();
String message = getLocalizedMessage();
return (message != null) ? (s + ": " + message) : s;
}
/**
*
* 列印出錯誤軌跡
*
*/
public void printStackTrace() {
printStackTrace(System.err);
}
/**
*
* 列印出錯誤軌跡
*
*/
public void printStackTrace(PrintStream s) {
synchronized (s) {
//調用當前對象的toString方法
s.println(this);
//擷取異常軌跡數組
StackTraceElement[] trace = getOurStackTrace();
//列印出每個元素的字串表示
for (int i=0; i < trace.length; i++)
s.println("/tat " + trace[i]);
//擷取起因對象
Throwable ourCause = getCause();
//遞迴的列印出起因對象的資訊
if (ourCause != null)
ourCause.printStackTraceAsCause(s, trace);
}
}
/**
*
* 列印起因對象的資訊
*
* @param s 列印的流
* @param causedTrace 有此對象引起的異常的異常軌跡
*
*/
private void printStackTraceAsCause(PrintStream s,
StackTraceElement[] causedTrace)
{
//獲得當前的異常軌跡
StackTraceElement[] trace = getOurStackTrace();
//m為當前異常軌跡數組的最後一個元素位置,
//n為當前對象引起的異常的異常軌跡數組的最後一個元素
int m = trace.length-1, n = causedTrace.length-1;
//分別從兩個數組的後面做迴圈,如果相等則一直迴圈,直到不等或數組到頭
while (m >= 0 && n >=0 && trace[m].equals(causedTrace[n])) {
m--; n--;
}
//相同的個數
int framesInCommon = trace.length - 1 - m;
//列印出不同的錯誤軌跡
s.println("Caused by: " + this);
for (int i=0; i <= m; i++)
s.println("/tat " + trace[i]);
//如果有相同的則列印出相同的個數
if (framesInCommon != 0)
s.println("/t... " + framesInCommon + " more");
//獲得此對象的起因對象,並遞迴列印出資訊
Throwable ourCause = getCause();
if (ourCause != null)
ourCause.printStackTraceAsCause(s, trace);
}
/**
*
* 列印出錯誤軌跡
*
*/
public void printStackTrace(PrintWriter s) {
synchronized (s) {
s.println(this);
StackTraceElement[] trace = getOurStackTrace();
for (int i=0; i < trace.length; i++)
s.println("/tat " + trace[i]);
Throwable ourCause = getCause();
if (ourCause != null)
ourCause.printStackTraceAsCause(s, trace);
}
}
/**
* 列印起因對象的資訊
*/
private void printStackTraceAsCause(PrintWriter s,
StackTraceElement[] causedTrace)
{
// assert Thread.holdsLock(s);
// Compute number of frames in common between this and caused
StackTraceElement[] trace = getOurStackTrace();
int m = trace.length-1, n = causedTrace.length-1;
while (m >= 0 && n >=0 && trace[m].equals(causedTrace[n])) {
m--; n--;
}
int framesInCommon = trace.length - 1 - m;
s.println("Caused by: " + this);
for (int i=0; i <= m; i++)
s.println("/tat " + trace[i]);
if (framesInCommon != 0)
s.println("/t... " + framesInCommon + " more");
// Recurse if we have a cause
Throwable ourCause = getCause();
if (ourCause != null)
ourCause.printStackTraceAsCause(s, trace);
}
/**
*
* 填充異常軌跡
*
*/
public synchronized native Throwable fillInStackTrace();
/**
*
* 返回當前的異常軌跡的拷貝
*
*/
public StackTraceElement[] getStackTrace() {
return (StackTraceElement[]) getOurStackTrace().clone();
}
/**
* 擷取當前的異常軌跡
*/
private synchronized StackTraceElement[] getOurStackTrace() {
//如果第一次調用此方法則初始化異常軌跡數組
if (stackTrace == null) {
//獲得異常軌跡深度
int depth = getStackTraceDepth();
//建立新的異常軌跡數組,並填充它
stackTrace = new StackTraceElement[depth];
for (int i=0; i < depth; i++)
stackTrace[i] = getStackTraceElement(i);//擷取指定位標的異常軌跡
}
return stackTrace;
}
/**
*
* 設定異常軌跡
*
*/
public void setStackTrace(StackTraceElement[] stackTrace) {
//拷貝設定參數
StackTraceElement[] defensiveCopy =
(StackTraceElement[]) stackTrace.clone();
//如果設定參數有空元素則拋出異常
for (int i = 0; i < defensiveCopy.length; i++)
if (defensiveCopy[i] == null)
throw new NullPointerException("stackTrace[" + i + "]");
//設定當前對象的異常軌跡
this.stackTrace = defensiveCopy;
}
/**
*
* 異常軌跡的深度,0表示無法獲得
*
*/
private native int getStackTraceDepth();
/**
*
* 擷取指定位標的異常軌跡
*
*/
private native StackTraceElement getStackTraceElement(int index);
private synchronized void writeObject(java.io.ObjectOutputStream s)
throws IOException
{
getOurStackTrace();
s.defaultWriteObject();
}
}