Bug分析之异常变量堆栈信息_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > Bug分析之异常变量堆栈信息

Bug分析之异常变量堆栈信息

 2011/12/21 9:10:00  jekiy  http://jekiy.iteye.com  我要评论(0)
  • 摘要:异常是一种特殊的类,在创建异常时会保存创建时的方法调用堆栈镜像。即,为了保留异常出现时的实时堆栈信息,不应复用异常,每个异常均需单独new方式生成。下面演示一段有问题的代码并进行分析1.问题代码a)自定义异常定义packagedemo.bce;publicclassMyExceptionextendsRuntimeException{privatestaticfinallongserialVersionUID=-3802919537257556719L;privateStringid
  • 标签:分析

?

?

?

异常是一种特殊的类,在创建异常时保存创建时的方法调用堆栈镜像。即,为了保留异常出现时的实时堆栈信息,不应复用异常,每个异常均需单独new方式生成。

?

下面演示一段有问题的代码并进行分析

?

1.问题代码

?

a自定义异常定义

package demo.bce;
 
public class MyException extends RuntimeException {
 
    private static final long serialVersionUID = -3802919537257556719L;
 
    private String id;
 
    public MyException(String id) {
       super();
       this.id = id;
    }
 
    public String getId() {
       return id;
    }
 
    public void setId(String id) {
       this.id = id;
    }
 
    @SuppressWarnings("unused")
    private MyException() {
    }
 
}

?


?

b)自定义异常常量

?

package demo.bce;
 
public final class MyExceptionContext {
 
    // x1,x2,y1,y2的Throw相关堆栈信息在创建时一次性生成(不再变化)
    // 即使用此异常会得到错误的堆栈描述信息
    public static final MyException x1 = new MyException("X1");
    public static final MyException x2 = new MyException("X2");
 
}

??


?

c)测试代码

?package demo.bce;

 
 
public class MyMain {
 
    public static void main(String[] args) {
       testx();
    }
 
    // ///
 
    private static void testx() {
       try {
           x11();
       } catch (Exception e) {
           e.printStackTrace();
       }
       try {
           x12();
       } catch (Exception e) {
           e.printStackTrace();
       }
       try {
           x21();
       } catch (Exception e) {
           e.printStackTrace();
       }
       try {
           x22();
       } catch (Exception e) {
           e.printStackTrace();
       }
    }
 
    private static void x11() {
       throw MyExceptionContext.x1;
    }
 
    private static void x12() {
       throw MyExceptionContext.x2;
    }
 
    private static void x21() {
       throw MyExceptionContext.x1;
    }
 
    private static void x22() {
       throw MyExceptionContext.x2;
    }
 
}
?


?

d)测试结果

?

demo.bce.MyException

??? at demo.bce.MyExceptionContext.<clinit>(MyExceptionContext.java:7)

??? at demo.bce.MyMain.x11(MyMain.java:36)

??? at demo.bce.MyMain.testx(MyMain.java:14)

??? at demo.bce.MyMain.main(MyMain.java:7)

demo.bce.MyException

??? at demo.bce.MyExceptionContext.<clinit>(MyExceptionContext.java:8)

??? at demo.bce.MyMain.x11(MyMain.java:36)

??? at demo.bce.MyMain.testx(MyMain.java:14)

??? at demo.bce.MyMain.main(MyMain.java:7)

demo.bce.MyException

??? at demo.bce.MyExceptionContext.<clinit>(MyExceptionContext.java:7)

??? at demo.bce.MyMain.x11(MyMain.java:36)

??? at demo.bce.MyMain.testx(MyMain.java:14)

??? at demo.bce.MyMain.main(MyMain.java:7)

demo.bce.MyException

??? at demo.bce.MyExceptionContext.<clinit>(MyExceptionContext.java:8)

??? at demo.bce.MyMain.x11(MyMain.java:36)

??? at demo.bce.MyMain.testx(MyMain.java:14)

??? at demo.bce.MyMain.main(MyMain.java:7)

?

?

代码实际上在四个不同的方法中抛出了两个不同的异常,但抛到四个异常的堆栈信息居然完全一致。

?

另外,x11x21虽然抛同一个异常,但x11的异常无stackTracex21的异常有stackTrace信息。

?

2.代码分析和猜想

?

MyExceptionContext首次被调用时才生成常量异常x1x2。注意x1x2是同时生成的,且基本上处于相同的方法调用环境。故x1x2的方法调用堆栈信息基本一致,进而在实际使用时严重误导异常的抛出分析。

?

另外,通常情况下,异常是需要设置cause的。因此,也不应该尝试常量异常(cause每次可能不一样)。

?

3.简单总结

?

使用异常时实时new一个出来返回以获取正确方法调用堆栈信息。

??

?

?

?

发表评论
用户名: 匿名