JVM学习笔记5:异常处理

异常的分类

  • 显式:主体是应用程序,它指的是在程序中使用“throw”关键字,手动将异常实例抛出。
  • 隐式:主体则是 Java 虚拟机,它指的是 Java 虚拟机在执行过程中,碰到无法继续执行的异常状态,自动抛出异常。举例来说,Java 虚拟机在执行读取数组操作时,发现输入的索引值是负数,故而抛出数组索引越界异常(ArrayIndexOutOfBoundsException)。

异常的使用

  • 和C#一样使用try-catch-finally语法
  • try中出异常执行catch,然后执行finally
  • catch中出异常依旧走finally,但是最后还是会throw catch中的异常。
  • finally 代码块也触发了异常,那么只好中断当前 finally 代码块的执行,并往外抛异常。
  • catch用法与C#完全一样,可以定义多个catch块来监听不同的异常类型。同样,前面的 catch 代码块所捕获的异常类型不能覆盖后边的,否则编译器会报错。
  • catch也是会逐层去找的,也就是说一个函数如果没有catch到,那么会去到调用这个函数的代码块去找。理论上main加个catch应该可以hold住所有。

异常的JVM实现

  • 从字节码角度看每个函数后面有一个异常处理表。
  • from 指针和 to 指针分别为 0 和 3,代表它的监控范围从索引为 0 的字节码开始,到索引为 3 的字节码结束(不包括 3)。该条目的 target 指针是 6,代表这个异常处理器从索引为 6 的字节码开始。条目的最后一列,代表该异常处理器所捕获的异常类型正是 Exception。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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 // 异常表条目
  • try-catch-finally的字节码。从这个代码中可以看到为何finally块会执行呢?就是因为finally块被嵌入到了try\catch里面。 最后如果
  • 下面这个图很形象的反应了代码

image

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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 -c Foo
...
public void test();
Code:
0: aload_0
1: iconst_0
2: putfield #20 // Field tryBlock:I
5: goto 30
8: astore_1
9: aload_0
10: iconst_1
11: putfield #22 // Field catchBlock:I
14: aload_0
15: iconst_2
16: putfield #24 // Field finallyBlock:I
19: goto 35
22: astore_2
23: aload_0
24: iconst_2
25: putfield #24 // Field finallyBlock:I
28: aload_2
29: athrow // catch块如果也异常了
30: aload_0
31: iconst_2
32: putfield #24 // Field finallyBlock:I
35: aload_0
36: iconst_3
37: putfield #26 // Field methodExit:I
40: return
Exception table:
from to target type
0 5 8 Class java/lang/Exception
0 14 22 any

...
  • 需要注意的是如果catch块异常了,最后的finally捕获的是新异常。

语法糖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Foo implements AutoCloseable {
private final String name;
public Foo(String name) { this.name = name; }

@Override
public void close() {
throw new RuntimeException(name);
}

public static void main(String[] args) {
try (Foo foo0 = new Foo("Foo0"); // try-with-resources
Foo foo1 = new Foo("Foo1");
Foo foo2 = new Foo("Foo2")) {
throw new RuntimeException("Initial");
}
}
}
  • 这个就是java版的using
# Java
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×