《深入理解Java虚拟机》- JVM如何进行异常处理
一、Java异常
在程序中,错误可能产生于程序员没有预料到的各种情况,或者超出程序员可控范围的环境,例如用户的坏数据、试图打开一个不存在的文件等。为了能够及时有效地处理程序中的运行错误,Java 专门引入了异常类。
二、Java常见异常分类

三、为什么产生异常
在 Java 中一个异常的产生,主要有如下三种原因:
- Java 内部错误发生异常,Java 虚拟机产生的异常。
- 编写的程序代码中的错误所产生的异常,例如空指针异常、数组越界异常等。这种异常称为未检査的异常,一般需要在某些类中集中处理这些异常。
- 通过 throw 语句手动生成的异常,这种异常称为检査的异常,一般用来告知该方法的调用者一些必要的信息。
四、碰到异常怎么办?
我们把生成异常对象,并把它提交给运行时系统的过程称为拋出(throw)异常。运行时系统在方法的调用栈中查找,直到找到能够处理该类型异常的对象,这一个过程称为捕获(catch)异常。
Java 异常强制用户考虑程序的强健性和安全性。异常处理不应用来控制程序的正常流程,其主要作用是捕获程序在运行时发生的异常并进行相应处理。编写代码处理某个方法可能出现的异常,可遵循如下三个原则:
- 在当前方法声明中使用 try catch 语句捕获异常。
- 一个方法被覆盖时,覆盖它的方法必须拋出相同的异常或异常的子类。
- 如果父类抛出多个异常,则覆盖方法必须拋出那些异常的一个子集,而不能拋出新异常。
(引用:http://c.biancheng.net/view/1038.html)
五、从JVM角度看异常的产生与表达
先看示例代码:
public class Foo {
private int tryBlock;
private int catchBlock;
private int finallyBlock;
private int methodExit;
public void test() {
try {
tryBlock = 0;
} catch (Exception e) {
catchBlock = 1;
} finally {
finallyBlock = 2;
}
methodExit = 3;
}
}
这段代码是一段简单的异常处理代码,我们可以通过javap查看class文件的表达形式:
public void test();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=3, args_size=1
0: aload_0
1: iconst_0
2: putfield #2 // Field tryBlock:I
5: aload_0
6: iconst_2
7: putfield #3 // Field finallyBlock:I
10: goto 35
13: astore_1
14: aload_0
15: iconst_1
16: putfield #5 // Field catchBlock:I
19: aload_0
20: iconst_2
21: putfield #3 // Field finallyBlock:I
24: goto 35
27: astore_2
28: aload_0
29: iconst_2
30: putfield #3 // Field finallyBlock:I
33: aload_2
34: athrow
35: aload_0
36: iconst_3
37: putfield #6 // Field methodExit:I
40: return
Exception table:
from to target type
0 5 13 Class java/lang/Exception
0 5 27 any
13 19 27 any
LineNumberTable:
line 10: 0
line 14: 5
line 15: 10
line 11: 13
line 12: 14
line 14: 19
line 15: 24
line 14: 27
line 16: 35
line 17: 40
StackMapTable: number_of_entries = 3
frame_type = 77 /* same_locals_1_stack_item */
stack = [ class java/lang/Exception ]
frame_type = 77 /* same_locals_1_stack_item */
stack = [ class java/lang/Throwable ]
frame_type = 7 /* same */
从字节码中的注释可以看到,finally块被添加到了三个地方。也就是说,在从java代码翻译成字节码文件时,jvm会为try块和catch块生成finally 块里的逻辑。但是想想,为什么是三个“finally”呢? 最后一个finally 是为在catch块中的代码执行时发生异常而准备的。那么,有人会问,finally块的代码如果还有报错怎么办呢? 这里,引进没有被本人证实的事实:会往外抛出去,给上一层代码进行处理。
这里说明一下黄色部分的字节码:
exception table 表示异常表,异常表是用于存储代码中涉及到的所有异常,每个类编译后,都会跟随一个异常表,如果发生异常,首先在异常表中查找对应的行(即代码中相应的
try{}catch(){}代码块),如果找到,则跳转到异常处理代码执行,如果没有找到,则返回(执行 finally 之后),并 copy 异常的应用给父调用者,接着查询父调用的异常表,以此类推。from...to:表示异常处理器监控的范围(比如try块包含的代码)
target:表示异常处理器起始的位置(比如catch块包含的代码)
type:就是处理的异常
那么,发生异常后,如何对照异常表?
当程序触发异常后,Java虚拟机会从上到下遍历异常表中的条目。当触发异常的字节码的索引值在某个异常表条目的监控范围内,Java虚拟机会判断所抛出的异常和该条目想要捕获的异常是否匹配。如果匹配,Java虚拟机会将控制流转移到该条目的target指针指向的代码上,继续程序运行。
下面,提及的字节码解析一下异常表:
程序开始,运行到1:iconst_0时,发生Exception异常,此时程序会去便利方法表,从第一行开始,检测到 0<1<5,符合第一条目检测范围,接着再查看抛出的异常为Exception,符合该条目捕获处理的异常,后跳转至序号13字节码继续运行。若再在14:aload_0发生异常时,程序就又跳到异常表,查找匹配异常条目,最终找到target为序号为27的字节码,然后便一直往下走完所有字节码。
上例子中,属于在catch块发生异常,所以会看到字节码后还有一个athrow的步骤,也就是往外抛出异常啦。
好了,Jvm看异常到此。
(引:极客时间)
《深入理解Java虚拟机》- JVM如何进行异常处理的更多相关文章
- 深入理解JAVA虚拟机JVM
深入理解JAVA虚拟机JVM Java 虚拟机(Java virtual machine,JVM)是运行 Java 程序必不可少的机制.java之所以能实现一次编写到处执行,也就是因为jVM.原理:编 ...
- 深入理解java虚拟机JVM(下)
深入理解java虚拟机JVM(下) 链接:https://pan.baidu.com/s/1c6pZjLeMQqc9t-OXvUM66w 提取码:uwak 复制这段内容后打开百度网盘手机App,操作更 ...
- 深入理解java虚拟机JVM(上)
深入理解java虚拟机JVM(上) 链接:https://pan.baidu.com/s/1c6pZjLeMQqc9t-OXvUM66w 提取码:uwak 复制这段内容后打开百度网盘手机App,操作更 ...
- 什么是HotSpot VM & 深入理解Java虚拟机 JVM
参考 http://book.2cto.com/201306/25434.html 另外,这篇文章也是从一个系列中得出的: <深入理解Java虚拟机:JVM高级特性与最佳实践(第2版)> ...
- 深入理解Java虚拟机-JVM运行时数据区域
一.运行时数据区域 1.程序计数器 程序计数器( Program Counter Register) 是一块较小的内存空间, 它可以看作是当前线程所执行的字节码的行号指示器. Java虚拟机的多线程是 ...
- 深入理解Java虚拟机—JVM内存结构
1.概述 jvm内存分为线程共享区和线程独占区,线程独占区主要包括虚拟机栈.本地方法栈.程序计数器:线程共享区包括堆和方法区 2.线程独占区 虚拟机栈 虚拟机栈描述的是java方法执行的动态内存模型, ...
- JVM | 第1部分:自动内存管理与性能调优《深入理解 Java 虚拟机》
目录 前言 1. 自动内存管理 1.1 JVM运行时数据区 1.2 Java 内存结构 1.3 HotSpot 虚拟机创建对象 1.4 HotSpot 虚拟机的对象内存布局 1.5 访问对象 2. 垃 ...
- 《深入理解Java虚拟机:JVM高级特性与最佳实践》【PDF】下载
<深入理解Java虚拟机:JVM高级特性与最佳实践>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230062566 内容简介 作为一位 ...
- 《深入理解 java虚拟机》学习笔记
java内存区域详解 以下内容参考自<深入理解 java虚拟机 JVM高级特性与最佳实践>,其中图片大多取自网络与本书,以供学习和参考.
- (1) 深入理解Java虚拟机到底是什么?
好文转载:http://blog.csdn.net/zhangjg_blog/article/details/20380971 什么是Java虚拟机 作为一个Java程序员,我们每天都在写Java ...
随机推荐
- Java编程思想:为什么要使用内部类
public class Test { public static void main(String[] args) { Callbacks.test(); } } /* 为什么需要内部类: 1.可以 ...
- 文件传输——TCP/IP协议介绍总结
一.链路层 数据链路层的工作特性: 1.为IP模块发送和接收IP数据报2.为ARP模块发送ARP请求和接收ARP应答(ARP:地址解析协议,将IP地址转换成MAC地址)3.为RARP发送RARP请求和 ...
- python基础知识五 各类型数据方法补充,转换,分类,编码+坑中菜
3.9各类型数据方法补充,转换,分类,编码,坑中菜 3.9.1数据类型方法补充 1.str:不可变 补充方法 s1.capitalize():首字母大写 s1 = "alex" s ...
- YuniKorn 介绍
一.YuniKorn 简介 YuniKorn 是一种轻量级的通用资源调度程序,适用于容器编排系统.它的创建是为了一方面在大规模,多租户环境中有效地实现各种工作负载的细粒度资源共享,另一方面可以动态地创 ...
- 【CYH-02】NOIp考砸后虐题赛:函数:题解
这道题貌似只有@AKEE 大佬A掉,恭喜! 还有因为c++中支持两个参数数量不同的相同名称的函数调用,所以当时就没改成两个函数,这里表示抱歉. 这道题可直接用指针+hash一下,然后就模拟即可. 代码 ...
- FFT中的一个常见小问题(递推式)
FFT中的一个常见小问题这里不细说FFT的内容,详细内容看这些就足以了解大概了小学生都能看懂的FFT!!!FFT详解补充——FFT中的二进制翻转问题主要是对学习过程中一个容易困扰的小问题进行解释,以便 ...
- fiddle知识点六、如何使用fiddle进行模拟弱网
为什么要模拟弱网 随着互联网的快速发展,越来越多的应用核心功能需要网络进行实现.同一应用在2G.3G.4G和WiFi的不停网络下,响应各有不同.但是因为现在的网络普遍为4G网络,为了保证应用在不同的网 ...
- JVM(一):久识你名,初居我心
聊聊JVM JVM,一个熟悉又陌生的名词,从认识Java的第一天起,我们就会听到这个名字,在参加工作的前一两年,面试的时候还会经常被问到JDK,JRE,JVM这三者的区别. JVM可以说和我们是老朋友 ...
- Spring 整合 ibatis
是的,真的是那个不好用的ibatis,不是好用的mybatis. 由于工作需要用到ibatis需要自己搭建环境,遇到了不少的坑,做一下记录. 一.环境配置 Maven JDK1.6 (非常重要,使用S ...
- Java初中级程序员面试题宝典
Java基础部分 &与&&区别? &和&&都是逻辑运算符,都是判断两边同时真则为真,否则为假:但是&&当第一个条件不成之后,后面的条件都 ...