c++如何让程序异常以后继续执行_Java虚拟机如何处理异常的(一)?

56636e8cedc0355878d0e7cb9371dab2.png
题图图片来源来自pixiv, 著作权归原作者所有,感谢作者, 如侵权必删.

往期文章目录

木兮木木:Java对象的内存布局

木兮木木:Java对象内存布局

木兮木木:Java虚拟机如执行方法调用的(二)?

木兮木木:Java虚拟机是如何执行方法调用的(一)?

木兮木木:Java垃圾回收(二)

木兮木木:Java垃圾回收(一)

木兮木木:Java虚拟机如何加载Java类?

木兮木木:Java代码是如何运行的?

木兮木木:Java常见垃圾收集器

木兮木木:Java垃圾回收算法

木兮木木:java创建对象过程

木兮木木:java虚拟机面试之内存区域划分

文章正文

Java里处理异常的两种方式是 捕捉异常抛出异常. 这两大要素共同实现程序控制流的非正常转移.
抛出异常分为 显示隐工两种方式. 「显示异常」的主体是应用程序, 它指的是在程序中使用「throw关键字」, 手动将异常实例「抛出」.
「隐式异常」的主体则是「Java虚拟机」. 它指的是Java虚拟机在执行过程中, 碰到无法继续执行的「异常状态」. 自动抛出「异常」. 比如说数组越界异常(ArrayIndexOutOfBoundsException).

捕捉异常涉及的三种代码块

  1. 「try」代码块
用来标记需要进行异常监控的代码.

2. 「catch」代码块

跟在「try」代码块之后, 用来捕获「try」代码块中触发的某种指定类型的异常.

除了声明所捕获的异常之外, 「catch」代码块还定义了针对该异常类型的「异常处理器」.

在Java中, 「try」代码块后面可以跟着多个「catch」代码块, 来捕获不同类型的异常.

Java虚拟机会从上至下匹配异常处理器. 因此, 「前面的catch」代码块所捕获的异常类型不能覆盖后边的, 否则编译器会报错.

3. 「finally」代码块

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

通常来说, 在程序正常执行的情况下, 「finally」里的代码块会在「try」代码块执行之后运行;

01a0f0db2f9d3520555aa1b022ea6a06.png
程序正常执行异常处理

如果「try」代码块里触发了异常, 如果该异常没有被捕获, 那么「finally」代码块会直接运行, 并且在运行之后重新抛出该异常.

108cad4a79ab1d00f75882c7d86b377b.png
异常处理

如果「catch」捕获到了异常, 「finally」代码块则在「catch」代码块之后运行;

5611af1b73b614b01ef2dd372ba86cfe.png
异常处理

如果catch代码中也触发了某种异常, 那么finally代码块同样会执行, 并会抛出在catch代码块触发的异常.

07714fed84a65b92311a482f528c7fce.png
异常处理

如果finally代码块里也出现了异常, 那么只好中断当前finaly代码块的执行, 并往外抛出异常.

afa3a73aaccf44e52c7baf018720a6cf.png
异常处理

异常的基本概念

Java中所有的异常都是「Throwable」类或者其子类实例.

3e2462ea7036f9014f96e280e1b5009c.png
异常
可以看出, Throwable有两大直接子类.
  • Error
    • 涵盖程序不应捕获的异常
  • Exception
    • 涵盖程序可能需要捕获并可能处理的异常.
Exception还有一个特殊的子类「RuntimeException」,用来表示「程序虽无法继续执行, 但是还可以抢救一下」的情况. 如索引值越界就是其中一种.

非检查异常

非检查异常(unchecked exception).

非检查异常包括两种

  • Error
  • RuntimeException
其它异常都属于「检查异常」(checked Exception)

在Java中所有的「检查异常(checked exception)」都需要程序「显示」地的捕获, 或者在方法声明中使用「throws」关键字标注.

通常情况下, 程序中的自定义异常应为「检查异常」, 以便最大利用Java编译器编译检查.

异常实例

异常实例的构造十分的昂贵.

这是由于在构造异常实例时, Java虚拟机便需要生成该异常的栈轨迹(stack trace). 该操作会会逐个访问当前线程的Java栈帧, 并且记录下各种调试信息, 包括栈帧所指向的方法名称、方法所在的类名称、方法所在的类名、文件名称及在代码中的第几行触发该异常.

在生成栈轨迹时, Java虚拟机会忽略掉异常构造器以及填充栈帧的Java方法(Throwable.fillInStackTrace), 直接从新建异常位置开始算起.

此外, Java虚拟机还会忽略标记为不可见的Java方法栈帧.

虚拟机捕获异常

在编译生成的字节码当中, 每个方法都附带一个「异常表」. 「异常表」的每一个条目代表一个异常处理.并且由「form」指针、「to」指针、「target」指针及所捕获的异常类构成.

这些指针的值是「字节码索引(bytecode index, bci)」用以定位字节码.

其中, from指针和to指针标示了该异常处理器所监控的范围. 如try代码块所覆盖的范围. target指针则指向异常处理器的起始位置, 例如catch代码块的起始位置.

总结

介绍了Java里异常处理机制.

Java里异常分类.

检查异常、非检查异常

下一篇看看JVM是如何处理异常的.

感谢阅读.

本篇完...

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值