Exception和Error的难兄难弟

Exception和Error都是继承Throwable,在Java中只有Throwable类型的实例才可以被抛出(throw)或者捕获(catch),它是异常处理机制的基本组成类型。

Error是在正常情况下,不大可能出现的情况,也就是不可预料的情况,绝大部分的Error都会导致程序(比如JVM自身)处于非正常的,不可恢复的状态。既然是非正常的状态,那么也就不需要捕获。

Exception是程序在运行期间出现可以预料的异常情况。异常可以分为可检查异常(checked)和不可检查(unchecked)异常,可检查异常在源代码里必须显示的捕获处理,这是编译期的一部分。不检查异常就是运行时(runtime)异常,类似NullPointerException(NPE空指针异常),ArrayIndexOutOfBoundsException之类的,通常是可以编码避免所谓的逻辑错误,具体根据需要判断是否要捕获异常进行处理,而这不在编译期范围之内。

下面说一下一些异常和错误代表的含义:

链接错误(LinkageError):同一个限定名的class类被多个不同的ClassLoader加载后,相互交叉使用导致类冲突的情况。

NoClassDefFoundError:是因为JAVA虚拟机在编译的时候可以找到这个类,但是在运行的时候找不到这个类了,有可能是jar破损

ClassNotFoundException是因为JAVA虚拟机在编译时期找不到导入的类,有可能是类名写错了,或者是类路径不对

UnsatisfiedLinkError:动态链接库没有你需要的功能,或者是动态链接库的位置设置的不对,项目没有加载到。

ExceptionInInitializerError:计算静态初始值或静态变量的初始值期间发生的异常。就是在计算一个静态变量a,需要静态变量b参与,然后这时候静态变量b还没初始化,这时候产生的异常。

VirtualMachineError:

OutOfMemoryError:简称OOM,内存溢出的异常。(1)PermGern Space,内存永久区,这块内存主要是用来存储class和meta信息的,在主程序运行期间,GC是不会对这块内存进行内存回收的。当项目中有很多的class时,会出现PermGen Space的错误信息。(2)Heap Space,堆空间超出了jvm设置的最大值,这时候第一步要查看程序中是否有死循环,或者哪些内存没释放,第二部查看设置的Heap Space size大小是否合适。(3)GC overhead limit exceeded,GC超过限制,判断程序中是不是创建了大量的临时对象和弱引用对象.....

 

StackOverflowError:当程序中栈的深度超过了jvm分配给线程的大小时就会报这个错误的,这就看程序中是否有循环调用而无法返回的情况发生。

运行的异常(RuntimeException):

NullPointerException:NPE,空指针异常。在一个空的对象上调用方法出现的异常,检查程序哪些地方有可能出现的NULL的地方,加判断可以防止出现NPE。

ClassCastException:类型转换异常,这是jvm检测到两个类型在转换之间不兼容出现的异常。

SecurityException:安全性异常,也就是访问权限的问题。

ArrayIndexOutOfBoundsException:数组越界异常,需要查看程序使用的索引是否超过了正常的索引。

异常处理的4个基本原则:

1      尽量不要捕获类是Exception这样的通用性的异常,而是应该捕获特定异常,这样就可以直观的显示我们异常处理的思路,有利于协同开发。

2       不要生吞(swallow)异常,就是捕获到异常了,却不做任何操作。

3       try-catch代码段会产生额外的性能开销,换句话说它会影响jvm对代码的某些优化,因此建议try仅包含有必要捕获的代码段。

4      不要用异常控制代码的流程,因为这比通常意义上的条件判断语句如if-else,switch要低效的多

我们在处理异常程序的时候,要遵循throw early,catch late原则。

相关文章: