jvm处理异常

版权声明: https://blog.csdn.net/qq_18298439/article/details/84632595

       在java中,异常处理主要是由抛出异常和捕获异常两大元素组成。这两个元素就组成java程序控制流的非正常转移。

       抛出异常分两种:显式和隐式。显式指的是在程序中通过throw关键字手动抛出异常实例,它的主体是应用程序;而隐式值指的是在jvm执行过程中,碰到无法继续执行的异常状态,自动抛出异常,它的主体是jvm。

捕获异常则涉及到了try-catch-finally代码块。

  1. try:标记需要异常监控的代码块
  2. catch:在try灾后,用来捕获try中触发的某种制定类型的异常
  3. finally:在try和catch之后,用来声明一段必会运行的代码块。就算在try或者catch里声明return语句,finally块也会继续执行。但如果声明的是System.exit(0),finally则不会执行。

基本概念
        在java中,所有异常都是Throwable类或子类的实例。Throwable有两个直接子类:Error和Exception。应用程序不应捕获Error,因为当触发Error时,执行状态已经无法恢复,需要中止当前线程或者jvm。Exception则是需要捕获并处理的异常。Exception里有个特殊的东西。叫RuntimeExcaption。表示程序虽然不能进行下去,但还可以抢救一下。RuntimeExcaption和Error都是java里的非检查异常。其他异常则属于检查异常。

       异常的实例构造很昂贵,这是因为在生成异常实例时,jvm需要生成该异常的调用栈信息。这操作要挨个的访问当前线程的java栈,并记录调用的各个信息。包括调用的类名,方法名,文件名以及抛异常的行数。在构造调用栈信息时,jvm会忽略掉异常构造器方法,异常信息填充的Throwable.fillInStackTrace方法以及标记为不可见的方法,直接从新建异常的代码开始算起。

jvm捕获异常
       在编译生成的字节码中,每个方法都会有一个异常表。异常表的每一条都代表一个异常处理器。有from指针,to指针、target指针和锁捕获的异常类型构成。这下指针的值是字节码索引bci,用来定位字节码。from和to指针标示了异常处理器要监控的范围,即try代码块的内容。target指针则是catch代码块的起始位置。当发生异常时,jvm会从上至下遍历所有的数据,当触发异常的字节码索引在某个from-to范围内,jvm就会判断抛出异常的类型和该条要捕获的异常的类型匹配的时候,jvm的控制流就会转向该catch块的字节码。如果遍历完之后还没找到对应的类型,jvm就会沿着调用栈向上执行同样的操作。在最坏的情况下,jvm会遍历这个调用栈的每一个调用者。

       而对于finally块,jvm是把这个finally块的字节码复制到 try-catch块的所有正常退出,异常退出的出口那。
 

猜你喜欢

转载自blog.csdn.net/qq_18298439/article/details/84632595
今日推荐