程序运行过程中可以预料到的意外情况,在程序中可以进行捕获并进行相应的处理。意思就是:这种异常发生在程序内,可以进行try..catch处理。
必须在代码中显示的进行捕获处理,编译期会进行这一部分的检查。例如下面的代码:
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
也就是运行时异常(RuntimeException),例如NullPointerException、ArrayIndexOutOfBoundsException等。这类的异常时可以编码避免的逻辑错误。并不会强制必须要捕获。
绝大部分的Error会导致程序(Jvm)处于不正常、不可恢复的状态,所以不便于也不需要捕获,例如OutOfMemoryError。
不要捕获Exception这样的通用异常,应该捕获抛出的特定异常。
不要只捕获,不处理,忽略异常处理没有进行日志记录,使得诊断错误难以进行。例如下面的代码
try {
Thread.sleep(1000);
//应该捕获InterruptedException
} catch (Exception e) {
//直接打印没有进行日志记录
e.printStackTrace();
}finally {
.....
}
不要在异常的日志中记录用户隐私,例如机器名,IP,端口等
try-catch会产生额外的性能开销,会影响jvm对代码的优化,不要用大的try包住大段代码
每实例化一个Exception,会对当时的栈进行快照,频繁操作会有巨大的开销
不要在finally代码块中处理返回值
try代码块中的break或continue会使代码进入finally代码块
一个是Error,一个是Exception,我们不应该从Error中恢复程序运行,但可以从Exception中恢复程序运行。
如果JVM或者ClassLoader实例尝试加载(可以通过正常的方法调用,也可能是使用new来创建新的对象)类的时候却找不到类的定义。要查找的类在编译的时候是存在的,运行的时候却找不到了。这个时候就会导致NoClassDefFoundError。
造成该问题的原因可能是打包过程漏掉了部分类,或者jar包出现损坏或者篡改。解决这个问题的办法是查找那些在开发期间存在于类路径下但在运行期间却不在类路径下的类。
Java使用反射方式在运行时动态加载类,例如使用Class.forName方法来动态地加载类,任意一个类的类名如果被作为参数传递给这个方法都将导致该类被加载到JVM内存中,如果这个类在类路径中没有被找到,那么此时就会在运行时抛出ClassNotFoundException异常。 解决该问题需要确保所需的类连同它依赖的包存在于类路径中,常见问题在于类名书写错误。
还有一个导致ClassNotFoundException的原因就是:当一个类已经被类加载器加载到内存中了,此时另一个类加载器又尝试着动态地从同一个包中加载这个类。通过控制动态类加载过程,可以避免上述情况发生。