JAVA 篇之异常
JAVA 篇之异常
开源大法好啊 发表于9个月前
JAVA 篇之异常
  • 发表于 9个月前
  • 阅读 11
  • 收藏 0
  • 点赞 0
  • 评论 0

【腾讯云】新注册用户域名抢购1元起>>>   

1、结构

最顶层的类是序列化类,作用,异常堆栈信息可以通过网络流传送,Throwable是顶层的异常类(你可以看到所有的子类的构造函数都是调用父类的构造器,最后到达Throwable),Exception作为Throwable和其他异常的桥梁(这样更好的扩展异常类,比如自定义异常)。

2、异常的栈信息是怎么打印出来的

我们接触最多的就是异常可以帮助我们打印堆栈信息,下面通过一个列子说明

try {
    InputStream inputStream = new FileInputStream("D://aa");
} catch (FileNotFoundException e) {
    e.printStackTrace();
}

主要是看printStackTrace()栈的源码

synchronized (s.lock()) {
    // Print our stack trace
    s.println(this);
    StackTraceElement[] trace = getOurStackTrace(); //获取堆栈信息
    for (StackTraceElement traceElement : trace)
        s.println("\tat " + traceElement);

    // Print suppressed exceptions, if any
    for (Throwable se : getSuppressed())
        se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu);

    // Print cause, if any
    Throwable ourCause = getCause();
    if (ourCause != null)
        ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu);
}

getOurStackTrace()源码

if (stackTrace == UNASSIGNED_STACK ||
    (stackTrace == null && backtrace != null) /* Out of protocol state */) {
    int depth = getStackTraceDepth(); //获取栈的深度
    stackTrace = new StackTraceElement[depth];  
    for (int i=0; i < depth; i++)
        stackTrace[i] = getStackTraceElement(i);  //获取栈的信息
} else if (stackTrace == null) {
    return UNASSIGNED_STACK;
}

getStackTraceDepth() 和 getStackTraceElement(i)

native int getStackTraceDepth(); //本地方法
native StackTraceElement getStackTraceElement(int index); //本地方法

上诉方法都是在Throwable,从源码可见,其实栈的信息最后都是通过顶层父类Throwable中的方法打印出来,栈的信息是本地方法获取,最后看下异常信息

java.io.FileNotFoundException: D:\aa (系统找不到指定的文件。) 
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(FileInputStream.java:195)
    at java.io.FileInputStream.<init>(FileInputStream.java:138)
    at java.io.FileInputStream.<init>(FileInputStream.java:93)
    at main.test.Throw.main(Throw.java:30)

如果你仔细看new FileInputStream(String name)构造器的源码的话你会看到执行流程

public FileInputStream(String name) throws FileNotFoundException {
    this(name != null ? new File(name) : null);
}
public FileInputStream(File file) throws FileNotFoundException {
    String name = (file != null ? file.getPath() : null);
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        security.checkRead(name);
    }
    if (name == null) {
        throw new NullPointerException();
    }
    if (file.isInvalid()) {
        throw new FileNotFoundException("Invalid file path");
    }
    fd = new FileDescriptor();
    fd.attach(this);
    path = name;
    open(name); //open
}
private void open(String name) throws FileNotFoundException {
    open0(name);
}
private native void open0(String name) throws FileNotFoundException;

看到没有这个是入栈的操作(知识:每个方法都代码一个栈帧),出栈的顺序和入栈顺序是相反的(所以说栈是先进后出的)。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

标签: Java
  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 2
博文 40
码字总数 17798
×
开源大法好啊
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: