Throwable是java程序所有错误的父类。包括error和excepetin。
Error
简单理解,无法预期的严重错误无法(其实是不应该)任何回复操作。JVM回立刻退出。
如果深究,其实Error也可以catch住的。但是一般没啥意义,比如说OOM,所有线程都会再下面的操作中继续重复OOM。
public static void main(String[] args) {
try{
test();
}catch (Throwable e){
System.out.println("catch!");
e.printStackTrace();
}
System.out.println("finish");
}
private static int test(){
return test();
}
上面的代码回打印处finish。说明ERROR也是可以catch的。包括NoClassDefFoundError之类的Error都是可以捕获的。而且,Error即使不捕获,ERROR也影响只当前线程,不会导致JVM退出。下面代码运行JVM不会自动退出。
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();//即使Kill -9 这一块也不会被执行到!!
}
}
}
});
thread.start();
test();
}
private static int test(){
return test();
}
多说一句,Kill -9 不会触发任何异常和Error。
所以使用KILL指令强行清除java进程时可能会造成一些问题,如TCP连接单方面关闭等。
java异常简介
exception提供了两类,一类是runtime exception 一类是checked exception(除了RuntimeException子类的所有异常)。对于后一种包括我们常见的IO异常和SQL异常,必须对这些异常进行catch。
常见的runtimeexception有
NullPointerException - 空指针引用异常
ClassCastException - 类型强制转换异常。
IllegalArgumentException - 传递非法参数异常。
ArithmeticException - 算术运算异常
ArrayStoreException - 向数组中存放与声明类型不兼容对象异常
IndexOutOfBoundsException - 下标越界异常
NegativeArraySizeException - 创建一个大小为负数的数组错误异常
NumberFormatException - 数字格式异常
SecurityException - 安全异常
UnsupportedOperationException - 不支持的操作异常.
…
runtimeexception的设计初衷是JVM常用操作引发的错误。
下面的代码会在运行时报错。但是完全可以通过编译。
public class Test
{
public static void main(String[] args)
{
int a[]={2,3,5,32,6};
for (int i = 0; i <5; i++)
{
System.out.print(a[i]);
}
}
}
如果是checcked exception,在编译时就会被检查。所以,必须处理或者抛出。否则编译失败
Exception和Error的区别
NoClassDefFoundError VS ClassNotFoundException
NoClassDefFoundError一般是JVM通过默认的Classloader在进行类加载、链接的时候,找不对对应的Class文件而抛出来的,它的cause也是ClassNotFoundException。
ClassNotFoundException一般不会是直接抛出来的最上层的异常。现在很多项目都会使用第三方的框架或者运行在容器中,这些框架通常都会定义自己的Classloader去加载不同的类,然后通过反射去操作这些类。当找不对对应的Class文件时,自定义的Classloader也会抛出ClassNotFoundException,框架可以捕获这个异常,并将其包装成具体的异常,然后向上抛出。
- ClassNotFoundException是在类加载时找不到class文件时抛出的异常
- JVM默认的Classloader在遇到ClassNotFoundException时,会抛出NoClassDefFoundError
- 自定义Classloader进行管理类加载的框架或容器,在遇到ClassNotFoundException时,通常会抛出和当前具体错误相关的异常
java异常处理原则
java异常处理的三原则是具体明确,提早抛出,延迟捕获。最后一条是指不要在有能力处理异常之前捕获异常。假设你要为别人提供一个返回正负金额的方法供调用,返回值是Integer,就请不要再自己的程序内部捕获诸如网络错误的异常。因为你捕获了也没什么用,捕获后最大的处理也不过就是让返回值为null,这一点将更加让别人困惑。
反射的异常
具体实现中发生的异常(无论是runtime exception还是checked exception)会被包装为InvocationTargetException(这是一个runtime exception)。一旦发生异常,如果代理类在接口中没有声明,就会抛出UndeclaredThrowableException(这是一个RuntimeException,java.lang.reflect包和cglib中都有对应实现)。为了还原异常,你需要在动态代理的invoke方法中手动捕获异常,根据e.cause抛出新的异常。