给出如下异常信息:
java.lang.RuntimeException: level 2 exception at com.msh.demo.exceptionStack.Test.fun2(Test.java:17) at com.msh.demo.exceptionStack.Test.main(Test.java:24) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147) Caused by: java.io.IOException: level 1 exception at com.msh.demo.exceptionStack.Test.fun1(Test.java:10) at com.msh.demo.exceptionStack.Test.fun2(Test.java:15) ... 6 more
学这么多年Java,你真的会阅读Java的异常信息吗?你能说清楚异常抛出进程中的事件顺序吗?
需要内化的内容
写一个demo测试
上述异常信息在由一个demo发生:
package com.msh.demo.exceptionStack; import java.io.IOException; /** * Created by monkeysayhi on 2017/10/1. */ public class Test { private void fun1() throws IOException { throw new IOException("level 1 exception"); } private void fun2() { try { fun1(); } catch (IOException e) { throw new RuntimeException("level 2 exception", e); } } public static void main(String[] args) { try { new Test().fun2(); } catch (Exception e) { e.printStackTrace(); } } }
这次我复制了完整的文件内容,使文章中的代码行号和实际行号一一对应。
按照上述异常信息,异常抛出进程中的事件顺序是:
如何阅读异常信息
那么,如何阅读异常信息呢?有几点你需要认识清楚:
此刻,回过甚再去阅读示例的异常信息,是不是相当简朴?
为了辅佐领略,我尽大概通俗易懂的描写了异常信息的布局和构成元素,大概会引入一些马虎。阅读异常信息是Java措施猿的根基技术,但愿你能内化它,忘掉这些冗长的描写。
假如还不领略,发起你亲自追踪一次异常的建设和打印进程,利用示例代码即可,它很简朴但足够。难点在于异常是JVM提供的机制,你需要相识JVM的实现;且底层挪用了许多native要领,而追踪native代码没有那么利便。
扩展
为什么有时我在日志中只看到异常名”java.lang.NullPointerException”,却没有异常栈
示例的异常信息中,异常名、细节信息、路径三个元素都有,可是,由于JVM的优化,细节信息和路径大概会被省略。
这常常产生于处事器应用的日志中,由于沟通异常已被打印多次,假如继承打印沟通异常,JVM会省略掉细节信息和路径行列,向前翻阅即可找到完整的异常信息。
猴哥之前利用Yarn的Timeline Server时碰着过该问题。你能体会那种感受吗?卧槽,为什么只有异常名没有异常栈?没有异常栈怎么老子怎么知道那边抛出的异常?线上处事老子又不能停,劳务派遣管理系统,全靠日志了啊喂!
网上有不少沟通的case,好比NullPointerException丢失异常仓库信息,读者可以参照这个链接尝试一下。
如安在异常类中添加成员变量
为了得当的表达一个异常,我们有时候需要自界说异常,并添加一些成员变量,打印异常栈时,自动增补打印须要的信息。