获取Throwable异常 Catch Throwable Instead of Exception

AQUA ICONS SYSTEM QUESTION MARK 很多程序员习惯地用下面地方法打印异常:

try {
  ...
}catch(Exception e){
  e.printStackTrace();
}

实际上, 这是不足够的. 请看下面的例子:

Service srv;
public void doIt() throws Exception {
   try {
     srv = new Service();
   } catch (Exception e) {
     e.printStackTrace();
   } finally {
    srv.stopService(); // Line 150
  }
}

运行代码, 得到的结果是:

java.lang.NullPointerException
    at ....doIt(x.java:150)
    at ....main(x.java:195)

真正的异常没有被打印. 我们修改catch (Exception e) -> catch (Throwable e), 再次运行:

java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory
    at Logger.<init>(Logger.java:34)
    ...
Caused by: java.lang.ClassNotFoundException: org.slf4j.LoggerFactory
    at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
    at java.security.AccessController.doPrivileged(Native Method)
    ...
java.lang.NullPointerException
    at examples.modem.ReadMessages.doIt(ReadMessages.java:150)
    at examples.modem.ReadMessages.main(ReadMessages.java:195)

注意NoClassDefFoundError是一个Error, 而不是Exception - Error 和 Exception 同属Throwable. 详细关系参见Java API.

结论: 要打印所有异常和错误, 应该catch Throwable而不是catch Exception.