转载自http://www.jianshu.com/p/473c7b8b3bf3
Throwable
throwable类是所有的错误或异常的超类。只有对象是此类或其子类的实例之一时,才能通过JVM或者通过throw语句抛出。另外catch字句中的参数类型也必须是该类型。
Throwable包含两个子类:Error和Excaption。他们通常用于指示发生了异常情况。Throwable类和子类的两个构造方法:
- 不带参数
- 带String参数
Exception
Exception及其子类是Throwable的一种形式,它指出了合理的应用程序要想捕获的条件。对于可以恢复的条件使用“被检查异常”(Exception的子类中除了RuntimeException之外的其他子类),对于程序错误用“运行时异常”
RuntimeException
RuntimeException是那些可能在Java虚拟机正常运行期间抛出的异常的超类。编译器不会检查RuntimeException异常。例如,除数为0,抛出ArithmeticException异常。当程序中可能出现这类异常时,还是会编译通过。虽然java编译器不会检查运行异常,但是我们也可以通过throws进行声明抛出,也可以通过try-catch对它进行捕获处理。
Error
和Exception一样,Error也是Throwable的子类。它用于指示合理的应用程序不应该试图捕获的严重问题,大多数这样的错误都是异常条件。
和RuntimeException一样,编译器也不会检查Error。
java可将可抛出(Throwable)的异常分为是3种类型:被检查的异常(Checked Exception)、运行时异常(Runtime Exception)和错误(Error)
- 运行时异常
定义:RuntimeException 及其子类都被称为运行时异常。
ArithmeticException:当出现异常的运算条件时,抛出此异常。例如,一个整数“除以零”时,抛出此类的一个实例。
ClassCastException:当试图将对象强制转换为不是实例的子类时,抛出该异常。例如:Object x = new Integer(0);
LllegalArgumentException:抛出的异常表明向方法传递了一个不合法或不正确的参数。
IllegalStateException:在非法或不适当的时间调用方法时产生的信号。换句话说,即Java环境或Java应用程序没有处于请求操作所要求的适当状态下。
IndexOutOfBoundsException:指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。 应用程序可以为这个类创建子类,以指示类似的异常。
NoSuchElementException:由Enumeration的nextElement方法抛出,表明枚举中没有更多的元素。
NullPointerException:当应用程序试图在需要对象的地方使用null时,抛出该异常。这种情况包括:
调用null对象的实例方法。
访问或修改null对象的字段。
将null作为一个数组,获得其长度。
将null作为一个数组,访问或修改其时间片。
将null作为Throwable值抛出。
应用程序应该抛出该类的实例,指示其他对null对象的非法使用。
被检查的异常
定义:Exception类本身,以及其子类除了运行时异常之外其他的子类都属于被检查异常。
特点:java编译器会检查他,此类异常,要么通过throws进行声明描述,要么通过try-catch进行捕获处理,否则不能通过编译。例如,CloneNotSupportedException就属于被检查异常。当通过clone()接口去克隆一个对象,而该对象对应的类没有实现Cloneable接口,就会抛出CloneNotSupportedExeption异常,被检查的异常通常都是可以恢复的。错误
定义:Error类及其子类
特点:和运行时异常一样,编译器也不会对错误进行检查,当资源不足,约束失败、或是其他程序无法继续运行发生的条件发生时,就产生错误。程序本身无法修复这些错误的。例如,VirtuaMachineError就属于错误。
OOM
1.OutOfMemoryError异常
除了程序计数器外,虚拟机内存的其他几个运行区域都有发生OutOfMemoryError(OOM)异常的可能。
java Heap 溢出
一般的异常信息:java.lang.OutOfMemoryError:Java heap spacess
java堆用于存储对象实例,我们只要不断的创建对象,并且保证GC Roots到对象之间有可达路径来避免垃圾回收机制来清除这些对象,就会在对象到达最大堆容量限制后产生内存溢出异常。
出现这种异常,一般手段通过内存影响分析工具(如Eclipse Memory Analyzer)对dump出来的堆转存快照进行分析,重点是确认内存中的对象是否必要,先分清是因为内存泄漏(Memory Leak : 内存泄漏也称作"存储渗漏",用[动态存储]分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元。直到程序结束。(其实说白了就是该内存空间使用完毕之后未回收)即所谓内存泄漏。)还是内存溢出(Memory Overflow)。
如果是内存泄漏,引用可进一步通过工具查看泄漏对象到GC Roots的链。于是就能找到泄露对象时是通过怎样的途径导致垃圾收集器无法自动回收。
如果不存在内存泄漏,那就应该检查虚拟机的参数(-Xmx与-Xms)的设置是否适当。
2.虚拟机栈和本地方法栈溢出
如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常。
如果虚拟机无法申请到足够的内存空间,则抛出OutOfMemeryError异常
这里需要注意当栈的大小越大,可分配的线程就越小。
3、运行时常量池溢出
异常信息:java.lang.OutOfMemoryError:PermGen space
如果要向运行时常量池中添加内容,最简单的做法是使用String.interm()这个Native方法。该方法的作用是:如果池中已经包含了一个等于此String的字符串,则返回代表池中这个字符串的String对象,否则,将此String对象包含的字符串添加到常量池中,并且返回此String对象的引用。由于常量池分配在方法区内,我们可以通过-XX:PermSize和-XX:MaxPermSize限制方法区的大小,从而间接限制其中常量池的容量。
4、方法区溢出
方法区用于存放Class的相关信息、如类名、访问修饰符、常量池、字段描述、方法描述等。
异常信息:java.lang.OutOfMemoryError:PermGen space
方法区溢出也是一种常见的内存溢出异常,一个类如果要被垃圾收集器回收,判定条件是很苛刻的,经常动态生成的大量的Class的应用中,要特别注意这点。
SOF
程序中一旦出现死循环或者是大量的递归调用,在不断压栈过程中,造成栈容量超过默认大小而导致溢出。
栈溢出的原因:
- 递归调用
- 大量循环或死循环
- 全局变量是否过多
- 数组、List 、map数据过