所有程序都会有错误发生,我们叫它bug
-
异常情形如影随性的纠缠着,只有处理好这些异常情况才能保证服务正常期望运行,因此Java语言设计之初引入异常处理机制来规避异常于萌芽之中;
-
思考:
Exception与Error之间的区别是什么?
运行时异常与一般异常有什么区别? -
异常情况分类:Exception和Error
Exception:程序正常运行中,可以预料的意外情况,可能并且应该被捕获,进行相应处理。
Error:在正常情况下不可能出现的情况,绝大部分的Error都会导致程序(如:JVM)处理非正常状态、不可恢复状态。既然是非正常情况,所以不便于也不需要捕获,常见的比如OutOfMemoryError之类的都是Error的子类。 -
Exception又分为可检查(checked)异常和不检查(unchecked)异常,可检查异常在源代码里必须显式地进行捕获处理,这是编译期检查的一部分。
-
注意:这里不可查的Error是Throwable不是Exception
-
不检查异常就是运行时异常,类似NullPointerException、ArrayIndexOutOfBoundsException之类,具体根据需要来判断是否需要捕获,并不会再编译期强制要求。
-
理解Throwable、Exception、Error的设计和分类
-
由于代码堆栈不再是同步调用那种垂直的结构,我们往往看到的是特定的executor的堆栈,而不是业务方法调用关系,这种时候,我们怎么回溯问题呢?
-
答案:业务功能模块分配ID,在记录日志是将前后模块的ID进行调用关系的串联,一并跟任务信息,进行日志保存
-
Exception和Error都是继承Throwable类,而且在Java中只有Throwable类型的实例才可以被抛出(throw)或者捕获(catch),它是异常处理机制的基本组成类型。
-
Error、Exception或者RuntimeException有哪些?
-
NoClassDefFoundError和ClassNotFoundException有什么区别?
-
理解Java语言中操作Throwable的元素和实践
-
尽量不要捕获直接Exception这样的通用异常,而是应该捕获特定异常;需要了解可能会抛出的特定异常如IterruptedException
-
不要生吞异常,往往是基于假设这段代码不会发生,或者感觉忽略异常无所谓的,但是千万不要在产品代码中做这种假设
-
Throw early,catch late原则
- 自定义异常需要注意的点
-
是否需要定义成可检查的Exception(checked Exception),因为这种类型设计的初衷更是为了从宜昌情况恢复,作为异常设计者,我们往往有充足的信息进行异常分类
-
为保证诊断信息足够的同时,也要考虑避免包含敏感信息,因为那样可能导致潜在的安全问题。
如果我们看Java的标准类库,你可能注意到类似Java.net.ConnectionException,出错信息是类似“Connection refused”,而不包含具体的机器名、IP、端口等,一个重要考量就是信息安全。类似的情况在日志中也有,比如,用户数据一般是不可以输出到日志里面的。
总结Summary
- 当我们的服务出现反应变慢、吞吐量下降的时候,检查发生最频繁的Exception也是一种思路
- 假如你开车上山,车坏了,你拿出工具箱修一修,修好继续上路(Exception被捕获,从异常中恢复,继续程序的运行)
- 车坏了,你不知道怎么修,打电话告诉修车行,告诉你是什么问题,要车行过来修。(在当前的逻辑背景下,你不知道是怎么样的处理逻辑,把异常抛出去到更高的业务层来处理)
- 你打电话的时候,要尽量具体,不能只说我车动不了了。那修车行很难定位你的问题。(要补货特定的异常,不能捕获类似Exception的通用异常)
- 还有一种情况是,你开车上山,山塌了,这你还能修吗?(Error:导致你的运行环境进入不正常的状态,很难恢复)
网友评论