操作码9:finally子句

来源:互联网 发布:热血传奇手游脚本源码 编辑:程序博客网 时间:2024/06/17 10:31

字节码中的finally子句在方法内部的表现很像“微型子例程”,每个try语句块与其后面的结尾处都会调用finally子例程,finally子句结束后,隶属于这个finalyy子句的微型子例程执行返回操作,程序在第一次调用微型子例程的地方继续执行后面的语句。


jsr 跳转到子例程

jsr ,branchbyte1,branchbyte2


1.Java虚拟机首先将紧随jsr指令后的一个字长的的操作码地址(程序计数器)压入操作数栈

2.通过计算{(branchbtye1<<8)|branchbyte2 }来给定一个带符号16位偏移量

3.计算得出的偏移量加到jsr操作码上,虚拟机计算出目标(程序计算器)地址,

4.虚拟机跳转到目标位置,在新位置上执行操作。


jsr_w

jsr_w branchbyte1,branchbyte2,branchbyte3,branchbyte4

计算(branchbyte1<<24)|(branchbyte2<<16)|(branchbyte3<<8)|branchbyte4得到一个带符号的 32位偏移量



ret从子例程中返回

ret,index


1.从程序计数器设为存储在indext指定的局部变量中的returnAdress值

2.从returnAddress继续执行



当finally子句通过break,continue,return或者抛出异常退出时,被jsr指令压入的额外返回地址将从栈中移除,这时候ret将不再会被执行

一个finally子句退出有两种方式:1,ret退出,然后执行后面的;2.break,continue,return退出,此时不再执行后面子句


public boolean test(){

 try{

return true;

}finally{

break;

}

}return false;

}

此时return true不再执行,方法返回false;




每次进入finally前,先保存变量到局部变量,然后在执行完finally子句后,再从局部变量中获取值,然后使用

每次从finally返回的是保存的局部变量值,除非finally中有自己的返回语句(详见深入Jvm327)


public int test(boolean bVal){

try{

if(bVal){

return 1;

}

return 0;

}

finally{

System.out.println("sd")

}

0 iload_0 获取vVal值

1 ifeq 11 if判断

4 iconst_1 压入1到栈

5 istore_1 存储局部变量1

6 jsr 24 finally子例程跳转

9 iload_1  获得局部变量1

10 ireturn 返回局部标量1中的值

11 iconst_0 压入1 (if分支)

12  istore_1 存储局部变量1

13 jsr 24 条状子例程

16 iload_1 获取局部变量

17 ireturn 返回

18 astore _2 存储

19 jsr24

22aload_2

23 athrow 异常


子例程

24 astore_3 保存跳转地址到局部变量3中

25 getstatic#7

28ldc#1

30invokevirtual #8

33ret 3 返回到局部变量3保存的位置中



jsr包括三个jsr条状:if判断2个和一个异常捕获




0 0
原创粉丝点击