JVM如何处理异常深入详解

  

  

无论你是使用何种编程语言,在日常的开发过程中,都会不可避免的要处理异常。今天本文将尝试讲解一些JVM如何处理异常问题,希望能够讲清楚这个内部的机制,如果对大家有所启发和帮助,则甚好。

  


  

  

我们在标题中提到了异常,然而这里指的异常并不是单纯的例外,而是更为宽泛的Throwable。只是我们工作中习以为常的将它们(错误地)这样称谓。

  

关于异常和Throwable的关系简单描述一下

  
      <李>异常属于Throwable的子类,Throwable的另一个重要的子类是错误李   <李>扔可以抛出的都是Throwable和其子类,抓住可捕获的也和是Throwable其子类。
      李   
  

除此之外,但是例外也有一些需要我们再次强调的

  
      <李>异常分为两种类型,一种为检查异常,另一种为抛出未检测异常   <李>检查异常,比如最常见的IOException,这种异常需要调用处显式处理,要么使用尝试捉捕获,要么再次抛出去。   <李>未经检查的异常指的是所有继承自错误(包含自身)或者是RuntimeException(包含自身)的类,这些异常不强制在调用处进行处理。但是也可以尝试抓住处理。   
  

本文暂不做检查异常设计的好坏的分析。

  


  

  

提到JVM处理异常的机制,就需要提及异常表,以下称为异常表。我们暂且不急于介绍异常表,先看一个简单的Java处理异常的小例子。

        公共静态孔隙simpleTryCatch () {   尝试{   testNPE ();   }捕捉(异常e) {   e.printStackTrace ();   }   }      

上面的代码是一个很简单的例子,用来捕获处理一个潜在的空指针异常。

  

当然如果只是看简简单单的代码,我们很难看出什么高深之处,更没有了今天文章要谈论的内容。

  

所以这里我们需要借助一把神兵利器,它就是程序,一个用来拆解类文件的工具,和javac一样由JDK提供。

  

然后我们使用javap来分析这段代码(需要先使用javac编译)

     //javap - c主要   公共静态孔隙simpleTryCatch ();   代码:   0:invokestatic # 3//方法testNPE: V ()   3:转到11   6:astore_0   7:aload_0   8:invokevirtual # 5/java/lang/方法/Exception.printStackTrace: V ()   11:返回   异常表:   从目标类型   0 3 6类java/lang/异常      

看到上面的代码,应该会有会心一笑,因为终于看到了异常表,也就是我们要研究的异常表。

  

异常表中包含了一个或多个异常处理者(异常处理程序)的信息,这些信息包含如下

  
      <李>从可能发生异常的起始点李   <李>可能发生异常的结束点李   <李>目标上从和述之前发生异常后的异常处理者的位置李   <李>类型异常处理者处理的异常的类信息李   
  


  

  

答案是异常发生的时候,当一个异常发生时

  

1. jvm会在当前出现异常的方法中,查找异常表,是否有合适的处理者来处理

  

2。如果当前方法异常表不为空,并且异常符合处理者的从和节点,并且类型也匹配,则JVM调用位于目标的调用者来处理。

  

3。如果上一条未找到合理的处理者,则继续查找异常表中的剩余条目

  

4。如果当前方法的异常表无法处理,则向上查找(弹栈处理)刚刚调用该方法的调用处,并重复上面的操作。

  

5。如果所有的栈帧被弹出,仍然没有处理,则抛给当前的线程,线程则会终止。

  

6。如果当前线程为最后一个非守护线程,且未处理异常,则会导致JVM终止运行。

  

以上就是JVM处理异常的一些机制。

  


  

  

除了简单的try - catch外,我们还常常和最后做结合使用。比如这样的代码

        公共静态孔隙simpleTryCatchFinally () {   尝试{   testNPE ();   }捕捉(异常e) {   e.printStackTrace ();   最后}{   System.out.println(“最后”);   }   }      

同样我们使用javap分析一下代码

        公共静态孔隙simpleTryCatchFinally ();   代码:   0:invokestatic # 3//方法testNPE: V ()   3:getstatic # 6//java/lang/system . out:字段Ljava/io/PrintStream;   6:最后ldc # 7//字符串   8:invokevirtual # 8//java/io/PrintStream.println:方法(Ljava/lang/String;) V   11:转到41   14:astore_0   15:aload_0   16:invokevirtual # 5/java/lang/方法/Exception.printStackTrace: V ()   19:getstatic # 6//java/lang/system . out:字段Ljava/io/PrintStream;   22:ldc # 7//字符串最后   24:invokevirtual # 8//java/io/PrintStream.println:方法(Ljava/lang/String;) V   27:转到41   30:astore_1   31:getstatic # 6//java/lang/system . out:字段Ljava/io/PrintStream;   34:ldc # 7//字符串最后   36:invokevirtual # 8//java/io/PrintStream.println:方法(Ljava/lang/String;) V   39:aload_1   40:athrow   41:返回   异常表:   从目标类型   0 3 14类java/lang/例外   0 3 30任何   14日19日30任何

JVM如何处理异常深入详解