【05】JVM是如何处理异常的

一、异常的概念

所有异常都是Throwable类或者其子类的实例。

Throwable有两大直接子类,第一个是ERROR,涵盖程序不应捕获的异常,当程序触发Error时,其执行状态已经无法恢复,需要中止线程甚至是终止虚拟机;第二个是Exception,涵盖程序可能需要捕获并且处理的异常。

捕获异常涉及三种代码块

(1)try代码块:用来标记需要进行异常监控的代码

(2)catch代码块:跟在try代码块之后,用来捕获在try代码块中触发的某种特定类型的异常。Java虚拟机会从上而下匹配异常处理器,因此,前面的catch代码块所捕获的异常类型不能覆盖后边的,否则编译器会报错

(3)finally代码块:跟在try代码块和catch代码块之后,用来声明一段必定运行的代码。它的设计初衷是为了避免跳过某些关键的清理代码,例如关闭已经打开的系统资源。

二、Java虚拟机是如何捕获异常的

在编译生成的字节码中,每个方法都附带一个异常表。异常表中的每个条目代表一个异常处理器,由from指针、to指针、target指针及其所捕获的异常类型构成。这些指针的值是字节码索引,用以定位字节码。

java 复制代码
public static void main(String[] args) {
  try {
    mayThrowException();
  } catch (Exception e) {
    e.printStackTrace();
  }
}
// 对应的 Java 字节码
public static void main(java.lang.String[]);
  Code:
    0: invokestatic mayThrowException:()V
    3: goto 11
    6: astore_1
    7: aload_1
    8: invokevirtual java.lang.Exception.printStackTrace
   11: return
// 编译后,该方法异常表拥有如下一个条目
  Exception table:
    from  to target type
      0   3   6  Class java/lang/Exception  // 异常表条目
      
// from 为0 to 为 3代表它的监控范围从索引为0的字节码开始,到索引为3的字节码结束(不包括3)
// target为6代表该索引处理器从索引为6的字节码开始。
//type 代表异常处理器捕获的异常类型是Exception

当程序触发异常时,Java虚拟机会遍历异常表中的所有条目。当触发异常的字节码的索引值在异常条目的监控范围内,JVM会判断所抛出的异常和该条目想要捕获的异常是否匹配。若匹配,JVM会将控制流转移至该条目target指针指向的字节码。

若遍历完所有异常表条目,JVM仍未匹配到异常处理器,则会弹出对应的Java栈帧,并且在调用者中重复上述操作。

思考:

1:使用异常捕获的代码为什么比较耗费性能?

因为构造异常的实例比较耗性能。这从代码层面很难理解,不过站在JVM的角度来看就简单了,因为JVM在构造异常实例时需要生成该异常的栈轨迹。这个操作会逐一访问当前线程的栈帧,并且记录下各种调试信息,包括栈帧所指向方法的名字,方法所在的类名、文件名,以及在代码中的第几行触发该异常等信息。

虽然具体不清楚JVM的实现细节,但是看描述这件事情也是比较费时费力的。

2:finally是怎么实现无论异常与否都能被执行的?

这个事情是由编译器来实现的,现在的做法是这样的,编译器在编译Java代码时,会复制finally代码块的内容,然后分别放在try-catch代码块所有的正常执行路径及异常执行路径的出口中。

相关推荐
Ray Wang11 小时前
3.JVM
jvm
java6666688881 天前
Java中的对象生命周期管理:从Spring Bean到JVM对象的深度解析
java·jvm·spring
生产队队长1 天前
JVM(HotSpot):字符串常量池(StringTable)
jvm
Yuan_o_1 天前
JVM(Java Virtual Machine) 详解
jvm
派大星-?1 天前
JVM内存回收机制
jvm
G丶AEOM2 天前
Hotspot是什么?
jvm·hotspot
太阳伞下的阿呆2 天前
Java内存布局
jvm·内存对齐·内存布局·压缩指针
Tech Synapse2 天前
Java如何解决同时出库入库订单号自动获取问题
java·jvm·oracle
hiyo5852 天前
C#类的概念
java·jvm·c#
pumpkin845143 天前
JVM类数据共享(CDS)
java·jvm