异常捕获
-
字节码中存在一个 Exception table表,
- Exception table 表可以检测对应代码行,如有异常,会进行异常匹配,然后跳转对应匹配异常的代码行;
- 接着存储异常的局部变量 e【slot,槽位共用】,再执行程序;
-
异常的字节码:
- 在底层,会将fianlly中的代码复制三份,以确保,fianlly代码块中的代码一定会被执行;
- 第一份,复制到try代码块最后;
- 第二份,try代码块发生异常时,执行catch代码块,所以复制到catch代码的最后;
- 第三份,当catch中的异常无法匹配的时候,或者,在catch代码中又产生异常的时候,会跳转到第三代码块,存储此时的剩余异常,然后执行finally代码块内容;
try{ } catch { } finally{ }
- 在底层,会将fianlly中的代码复制三份,以确保,fianlly代码块中的代码一定会被执行;
-
当try和finally中同时存在 return,因为必须确保finally中的代码执行,因此会将try中的return值,暂时存储起来【存储到无名槽,固定返回值】,但当执行finally代码块中的return值时,就直接返回了。
-
同时禁止在finally中放return语句,因为抛出异常语句会在finally代码块后执行,当return之后,athrow语句就被吞了。
-
执行return i;会将i存储到无名槽【和i原本的槽不同,因此无法显式修改】,最后返回固定值;
int i = 10; try{return i; } finally {i = 20; } // 最后局部变量i=20,但是返回的是固定值10;
锁:synchronized代码块【正常解锁 和异常解锁】;
- 在进入 sychronized时,会将lock再复制一份,存储到无名槽,然后lock配合monitorenter使用,进入代码块;
- 代码块执行后,会再加载无名槽的lock对象,再配合monitorexit使用后,出代码块;
- 当在sychronized代码块中出现异常,或者2步骤中出现异常,会跳转到代码3【2步骤的复制代码 + athrow 异常抛出】;
Object lock = new Object();
synchronized(lock){
}
- 方法级别的synchronized不会再字节码指令中有所体现;