Java异常处理使用Throwable而不是Exception

线上问题

近期在线上系统中遇到了一个奇怪的问题,某个请求处理失败了,但是日志里没有任何错误信息,catch(Exception e) {}代码块根本没有执行,因此直接跳过了错误处理逻辑,但是finally{}块却执行了。根据此现象我们推测出很可能是代码块抛出了非Exception子类的异常。果然,将catch Exception改为catch Throwable后, 日志中出现了java.lang.IncompatibleClassChangeError异常。因为此异常是Error而不是Exception的子类,所以导致了出现catch{}没有执行但finally执行了的现象。

关于Exception

异常.png
在很多入门书上都会有类似于"Exception是可恢复的而Error往往是不可恢复的系统严重错误"这样的内容,当然,这句话本身是没问题的,问题在于即便是Error错误我们也应该捕获一下,至少要记一下日志,如果忽略掉的话就会出现上面这种莫名其妙失败但又找不到线索的情况。
经查,报java.lang.IncompatibleClassChangeError的原因是最近一次上线时引入了新的业务jar包,此依赖的某个传递依赖版本跟原有系统中的jar版本有冲突,导致JVM在执行时报错。这个问题之所以在测试时没有发现,还有一个原因,就是只有在执行到特定逻辑时才会触发,并不是每次都会出现,非常隐蔽。

如果偶尔看过Netty的代码,你会发现Netty所有的catch, 最后都是以catch(Throwable e)结尾的,而不是Exception。我们在编码时也应该以catch Throwable兜底, 不要再使用Exception了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章