每一个try语句块catch的异常都与异常表中的一项相对应,异常表中的每一项都包括:
例如:
用javap –c查看字节码如下:
可见ClassNotFoundException异常可能会在0~6之间抛出,9开始处的代码处理此异常。
当产生异常的时候,jvm将会在整个异常表中搜索与之匹配的项,如果当前pc在异常表入口所指的范围内,并且所抛出的异常是此入口所指向的类或者其子类,则跳转到对应的处理代码继续执行。
Class文件的attribute_info中保存有Exceptions属性,记录着每个方法throws的异常信息。具体的可以查看class类文件格式相关的文章。
athrow指令从栈顶弹出Throwable对象引用,抛出异常。
在jvm规范中,finally语句是通过jsr/jsr_w与ret指令实现的。当执行jsr/jsr_w的时候将finally执行完成后的返回地址压入栈中,进入finally后会马上将此地址保存到一个局部变量中,执行完成后,ret从此局部变量中取出返回地址。???为什么会先把返回地址保存到局部变量中呢???因为,当从finally语句返回的时候需要将返回地址成栈中弹出,当finally语句非正常结束(break,continue,return, 抛异常)的时候就不用再考虑这个问题。
以下是jvm规范中Compiling finally的一段:
当tryItOut排除任何异常后都将会被异常表中的any项捕获,执行完finally后,会执行athrow指令将异常抛出。
从jdk的某一个版本开始就不会编译出编译出含jsr/jsr_w、ret的字节码了,因为有指令上的缺陷,导致jvm的检验和分析系统出现漏洞。
在finally中使用break、continue、return、抛出异常等认为是finally的非正常结束。非正常结束的时候,ret指令不会被执行,很可能会出现意想不到的结果。如:
建议:在写finally语句的时候,尽量避免非正常结束!
posted on 2011-05-27 14:39 happyenjoylife 阅读(2558) 评论(4) 编辑 收藏
来学习了,谢谢博主的文章了。 回复 更多评论
不错哦 回复 更多评论
字节码,看不懂啊,去哪里学习啊? 回复 更多评论
@程先生字节码可以看jvm规范,也可以看《深入java虚拟机》,又可以上网找找 回复 更多评论