Jvm 学习——异常处理

异常表

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

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

 

例如:

public class Test {
    
public static void main(String[] args) {

        
try {
            Class.forName(
"java.lang.String");
        }
 catch (ClassNotFoundException e) {
            e.printStackTrace();
        }


    }

}

javap –c查看字节码如下:

 

Compiled from "Test.java"
public class Test extends java.lang.Object{
public Test();
  Code:
   
0:    aload_0
   
1:    invokespecial    #1//Method java/lang/Object."<init>":()V
   4:    return

public static void main(java.lang.String[]);
  Code:
   
0:    ldc    #2//String java.lang.String
   2:    invokestatic    #3//Method java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
   5:    pop    
   
6:    goto    14
   
9:    astore_1
   
10:    aload_1
   
11:    invokevirtual    #5//Method java/lang/ClassNotFoundException.printStackTrace:()V
   14:    return
  Exception table:
   from   to  target type
     
0     6     9   Class java/lang/ClassNotFoundException
}

 

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

 

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

 

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

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

 

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

 

finally语句

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

 

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

void tryFinally() {
    
try {
        tryItOut();
    }
 finally {
        wrapItUp();
    }

}

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

 

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

 

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

 

再说finally的非正常退出

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

 

public class Test {
    
public static boolean test(boolean b) {
        
while (b) {
            
try {
                
return true;
            }
 finally {
                
/*
                break;                          始终返回false
                continue;                         javac编译再java执行会出现死循环
                                                在eclipse中甚至会出现报错:提示找到不main class
                return false;                     始终返回false
                throw new RuntimeException("");    抛出异常
                 
*/

            }

        }


        
return false;
    }


    
public static void main(String[] args) {
        System.out.println(test(
true));
    }

}


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


 

posted on 2011-05-27 14:39 happyenjoylife 阅读(2558) 评论(4)  编辑  收藏

评论

# re: Jvm 学习——异常处理 2011-05-27 16:46 代孕

来学习了,谢谢博主的文章了。  回复  更多评论   

# re: Jvm 学习——异常处理 2011-05-27 22:02 爱课件

不错哦  回复  更多评论   

# re: Jvm 学习——异常处理 2011-06-03 11:35 程先生

字节码,看不懂啊,去哪里学习啊?  回复  更多评论   

# re: Jvm 学习——异常处理 2011-06-11 18:04 happyenjoylife

@程先生
字节码可以看jvm规范,也可以看《深入java虚拟机》,又可以上网找找
  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航:
 

导航

<2011年5月>
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

统计

常用链接

留言簿

随笔档案

搜索

最新评论

阅读排行榜

评论排行榜