首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

Jvm 学习——错误处理

2012-11-05 
Jvm 学习——异常处理异常表每一个try语句块catch的异常都与异常表中的一项相对应,异常表中的每一项都包括:

Jvm 学习——异常处理
异常表

每一个try语句块catch的异常都与异常表中的一项相对应,异常表中的每一项都包括:

    起点终点,始终把catch异常位置的pc指针偏移量的最大值大1?处理异常时跳转到的字节码序列中的pc指针偏移量?被catch的异常类的常量池索引

?

例如:

Jvm 学习——错误处理Jvm 学习——错误处理public?class?Test?Jvm 学习——错误处理{
Jvm 学习——错误处理Jvm 学习——错误处理????public?static?void?main(String[]?args)?Jvm 学习——错误处理{
Jvm 学习——错误处理
Jvm 学习——错误处理Jvm 学习——错误处理????????try?Jvm 学习——错误处理{
Jvm 学习——错误处理????????????Class.forName("java.lang.String");
Jvm 学习——错误处理Jvm 学习——错误处理????????}?catch?(ClassNotFoundException?e)?Jvm 学习——错误处理{
Jvm 学习——错误处理????????????e.printStackTrace();
Jvm 学习——错误处理????????}
Jvm 学习——错误处理
Jvm 学习——错误处理????}
Jvm 学习——错误处理}
Jvm 学习——错误处理

Compiled?from?"Test.java"
Jvm 学习——错误处理Jvm 学习——错误处理public?class?Test?extends?java.lang.ObjectJvm 学习——错误处理{
Jvm 学习——错误处理public?Test();
Jvm 学习——错误处理??Code:
Jvm 学习——错误处理???0:????aload_0
Jvm 学习——错误处理???1:????invokespecial????#1;?//Method?java/lang/Object."<init>":()V
Jvm 学习——错误处理???4:????return
Jvm 学习——错误处理
Jvm 学习——错误处理public?static?void?main(java.lang.String[]);
Jvm 学习——错误处理??Code:
Jvm 学习——错误处理???0:????ldc????#2;?//String?java.lang.String
Jvm 学习——错误处理???2:????invokestatic????#3;?//Method?java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
Jvm 学习——错误处理???5:????pop????
Jvm 学习——错误处理???6:????goto????14
Jvm 学习——错误处理???9:????astore_1
Jvm 学习——错误处理???10:????aload_1
Jvm 学习——错误处理???11:????invokevirtual????#5;?//Method?java/lang/ClassNotFoundException.printStackTrace:()V
Jvm 学习——错误处理???14:????return
Jvm 学习——错误处理??Exception?table:
Jvm 学习——错误处理???from???to??target?type
Jvm 学习——错误处理?????0?????6?????9???Class?java/lang/ClassNotFoundException
Jvm 学习——错误处理}
Jvm 学习——错误处理

?

可见ClassNotFoundException异常可能会在0~6之间抛出,9开始处的代码处理此异常。

?

当产生异常的时候,jvm将会在整个异常表中搜索与之匹配的项,如果当前pc在异常表入口所指的范围内,并且所抛出的异常是此入口所指向的类或者其子类,则跳转到对应的处理代码继续执行。

?

方法可能会抛出哪些已检查异常

Class文件的attribute_info中保存有Exceptions属性,记录着每个方法throws的异常信息。具体的可以查看class类文件格式相关的文章。

?

athrow指令从栈顶弹出Throwable对象引用,抛出异常。

?

finally语句

在jvm规范中,finally语句是通过jsr/jsr_w与ret指令实现的。当执行jsr/jsr_w的时候将finally执行完成后的返回地址压入栈中,进入finally后会马上将此地址保存到一个局部变量中,执行完成后,ret从此局部变量中取出返回地址。???为什么会先把返回地址保存到局部变量中呢???因为,当从finally语句返回的时候需要将返回地址成栈中弹出,当finally语句非正常结束(break,continue,return, 抛异常)的时候就不用再考虑这个问题。

?

以下是jvm规范中Compiling?finally的一段:

Jvm 学习——错误处理Jvm 学习——错误处理void?tryFinally()?Jvm 学习——错误处理{
Jvm 学习——错误处理Jvm 学习——错误处理????try?Jvm 学习——错误处理{
Jvm 学习——错误处理????????tryItOut();
Jvm 学习——错误处理Jvm 学习——错误处理????}?finally?Jvm 学习——错误处理{
Jvm 学习——错误处理????????wrapItUp();
Jvm 学习——错误处理????}
Jvm 学习——错误处理}
Jvm 学习——错误处理the?compiled?code?is
Jvm 学习——错误处理Method?void?tryFinally()
Jvm 学习——错误处理???0?????aload_0????????????//?Beginning?of?try?block
Jvm 学习——错误处理???1????invokevirtual?#6?????????//?Method?Example.tryItOut()V
Jvm 学习——错误处理???4?????jsr?14????????????//?Call?finally?block
Jvm 学习——错误处理???7?????return????????????//?End?of?try?block
Jvm 学习——错误处理???8?????astore_1????????????//?Beginning?of?handler?for?any?throw
Jvm 学习——错误处理???9?????jsr?14????????????//?Call?finally?block
Jvm 学习——错误处理??12?????aload_1????????????//?Push?thrown?value
Jvm 学习——错误处理??13?????athrow????????????//?Jvm 学习——错误处理and?rethrow?the?value?to?the?invoker
Jvm 学习——错误处理??14?????astore_2????????????//?Beginning?of?finally?block
Jvm 学习——错误处理??15?????aload_0????????????//?Push?this
Jvm 学习——错误处理??16?????invokevirtual?#5?????????//?Method?Example.wrapItUp()V
Jvm 学习——错误处理??19?????ret?2????????????//?Return?from?finally?block
Jvm 学习——错误处理Exception?table:
Jvm 学习——错误处理???????From?????To?????Target?????????Type
Jvm 学习——错误处理????0????????4????????8???????????any
Jvm 学习——错误处理

?

当tryItOut排除任何异常后都将会被异常表中的any项捕获,执行完finally后,会执行athrow指令将异常抛出。

?

从jdk的某一个版本开始就不会编译出编译出含jsr/jsr_w、ret的字节码了,因为有指令上的缺陷,导致jvm的检验和分析系统出现漏洞。

?

再说finally的非正常退出

在finally中使用break、continue、return、抛出异常等认为是finally的非正常结束。非正常结束的时候,ret指令不会被执行,很可能会出现意想不到的结果。如:

?

Jvm 学习——错误处理Jvm 学习——错误处理public?class?Test?Jvm 学习——错误处理{
Jvm 学习——错误处理Jvm 学习——错误处理????public?static?boolean?test(boolean?b)?Jvm 学习——错误处理{
Jvm 学习——错误处理Jvm 学习——错误处理????????while?(b)?Jvm 学习——错误处理{
Jvm 学习——错误处理Jvm 学习——错误处理????????????try?Jvm 学习——错误处理{
Jvm 学习——错误处理????????????????return?true;
Jvm 学习——错误处理Jvm 学习——错误处理????????????}?finally?Jvm 学习——错误处理{
Jvm 学习——错误处理Jvm 学习——错误处理????????????????/**//*
Jvm 学习——错误处理????????????????break;??????????????????????????始终返回false
Jvm 学习——错误处理????????????????continue;?????????????????????????javac编译再java执行会出现死循环
Jvm 学习——错误处理????????????????????????????????????????????????在eclipse中甚至会出现报错:提示找到不main?class
Jvm 学习——错误处理????????????????return?false;?????????????????????始终返回false
Jvm 学习——错误处理????????????????throw?new?RuntimeException("");????抛出异常
Jvm 学习——错误处理?????????????????*/
Jvm 学习——错误处理????????????}
Jvm 学习——错误处理????????}
Jvm 学习——错误处理
Jvm 学习——错误处理????????return?false;
Jvm 学习——错误处理????}
Jvm 学习——错误处理
Jvm 学习——错误处理Jvm 学习——错误处理????public?static?void?main(String[]?args)?Jvm 学习——错误处理{
Jvm 学习——错误处理????????System.out.println(test(true));
Jvm 学习——错误处理????}
Jvm 学习——错误处理}
Jvm 学习——错误处理


建议:在写finally语句的时候,尽量避免非正常结束!

热点排行