3.Java异常处理
3.1 运行时异常和非运行时异常
运行时异常也叫unchecked exception 不可查异常,只包含一类:RuntimeException
运行时异常,一般是由于程序的设计漏洞,代码逻辑错误而造成的,一旦发生,就会直接由虚拟机终止正在运行的程序
常见的运行时异常有:
- NullPointerException(空指针异常)
- IndexOutOfBoundsException(数组下标越界异常)
- ClassCastException(类型转换异常)
- ArrayStoreException(数据存储异常,操作数组时类型不一致)
非运行时异常也叫checked exception 可查异常,也叫编译异常
常见的非运行时异常有:
- IOException(IO异常)
- SQLException(SQL异常)
- ClassNotFoundException(类没有找到异常)
编译异常必须try{}catch{}进行捕获,否则不能通过编译
3.2 try、catch、finally的执行顺序
当try和catch中有return时,执行到return时,会先执行finally中的内容,然后再return,但是如果finally中有return,那会直接返回,不再回到try或者catch中
注意,try和catch的return可能不被执行,但是return后操作会被执行,比如:
int i = 0;
try {
i ++;
i = i / 0;
return i+=10;
} catch (Exception e) {
return i++;
} finally {
return i;
}
此时返回的i是2,因为虽然执行的return是finally中的,但是catch中的操作还是执行了的,只是到最后的return前,进入了finally,并通过finally的return返回
3.3 多个catch
如果有多个catch,且指定的异常之间有派生关系,那么子类型异常必须写在上边,没有派生关系的异常顺序无关
3.4 try-catch-resource
使用方式如下:
try (resource) {
} catch (Exception e) {
}
resource就是一些资源的创建操作,在这里创建的资源,会在try{}catch{}执行后自动关闭,但是,这些资源必须实现AutoCloseable接口
3.5 异常继承关系
- Error(错误):是程序无法处理的错误,表示运行应用程序中较严重问题
- Exception(异常):是程序本身可以处理的异常
异同:
- Error和Exception都继承了Throwable类,而只有继承了Throwable类的才能抛出或者捕获异常。
- Exception是java程序运行中可以预料的意外情况,可以并且应该被捕获。
- Error指正常情况不可能出现的错误,一旦出现,程序将进入不正常,不可恢复状态,且无法被捕获。常见的如:栈移除,内存溢出,线程死亡等。
3.5.1 常见Error
类名 | 介绍 |
---|---|
ThreadDeath | 线程死亡 |
VirtualMachineError | 虚拟机异常 |
VirtualMachineError-StackOverFlowError | 栈溢出异常 |
VirtualMachineError-OutofMemoryError | 内存溢出异常 |
3.5.2 常见异常
不可检查异常(运行时异常):
类名 | 介绍 |
---|---|
ClassCastExecption | 类型转换异常 |
StringIndexOutofBoundsExecption | 字符串索引越界 |
ArrayIndexOutofBoundsExecption | 数组索引越界 |
NullPointerExecption | 空指针异常 |
NumberFormatExecption | 转换数字异常 |
可检查异常:
类名 | 介绍 |
---|---|
NoSuchFieldExecption | 找不到字段 |
NoSuchMethodExecption | 找不到方法 |
ClassNoFoundExecption | 找不到类 |
IOExecption | IO异常 |
IOExecption-EOFExecption | 文件已结束 |
IOExecption- FieldNotFoundExecption | 文件未找到 |
SQLExecption | SQL异常 |
3.6 OutOfMemoryError
- java.lang.OutOfMemoryError: Java heap space-Heap内存溢出,意味着Young和Old generation的内存不够。可通过调整java启动参数 -Xms -Xmx 来增加Heap内存
- java.lang.OutOfMemoryError: unable to create new native thread-Stack空间不足以创建额外的线程,要么是创建的线程过多,要么是Stack空间确实小了。解决途径:1.通过-Xss启动参数减少单个线程栈大小,这样便能开更多线程(当然不能太小,太小会出现StackOverflowError);2.通过-Xms -Xmx 两参数减少Heap大小,将内存让给Stack(前提是保证Heap空间够用)
- java.lang.OutOfMemoryError: PermGen space-Permanent Generation空间不足,不能加载额外的类。调整-XX:PermSize= -XX:MaxPermSize= 两个参数来增大PermGen内存。
- java.lang.OutOfMemoryError: Requested array size exceeds VM limit-由于Heap空间不足(定义的数组太大)。正确的解决办法是修改程序逻辑,也可以通过-Xmx来增大堆内存
- GC花费了大量时间,但是只回收了少量内存也会报错,一是需要进行GC turning,二是需要优化程序逻辑
- java.lang.StackOverflowError:线程栈溢出,方法调用层次过多,或者线程栈太小。解决途径:优化程序设计,减少方法调用层次;调整-Xss参数增加线程栈大小
- java.lang.OutOfMemoryError: request bytes for . Out of swap space?当从本地堆分配内存失败时抛出OutOfMemoryError异常
- java.lang.OutOfMemoryError: (Native method)该异常表明本地方法遇到了一个内存分配问题
- java.lang.OutOfMemoryError: Direct buffer memory 从Direct Memory分配内存失败 XX:MaxDirectMemorySize=可以设置Direct内存的大小
- java.lang.OutOfMemoryError: GC overhead limit exceeded是 JDK6新增错误类型。当GC为释放很小空间占用大量时间时抛出。一般是因为堆太小。导致异常的原因:没有足够的内存。可以通过参数-XX:-UseGCOverheadLimit关闭这个特性
- java.lang.OutOfMemoryError: request bytes for . Out of swap space?从本地堆分配内存失败时抛出OutOfMemoryError异常,可通过调整java启动参数 -Xms -Xmx 来增加Heap内存
3.7 NoSuchMethodError和NoSuchMethodException
NoSuchMethodError:程序尝试调用类的方法而该类不具有该方法时抛出,通常由编译器捕获,当类发生了不兼容更新时可能出现,需要检查类的变更和类的使用,修改代码
NoSuchMethodException:无法找到某一特定方法时,抛出该异常,运行时异常,可能是环境异常,比如远程调用时,生产者和消费者版本不一致
3.8 NoSuchFieldError、NoSuchFieldException
NoSuchFieldError编译时异常
NoSuchFieldException运行时异常
3.9 断言
assert <boolean表达式> ? <错误信息表达式>
<错误信息表达式>可以为空,如果为空则抛出默认的AssertionError,不为空时作为参数传入AssertionError
- assert关键字需要在运行的时候显式开启才能生效
- assert关键字本意上是为了测试调试程序时使用
- assert断言失败将面临程序的退出
所以断言不能代替异常处理