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

6 篇文章 0 订阅
1 篇文章 0 订阅

 

 

 

异常是一种特殊的类,在创建异常时保存创建时的方法调用堆栈镜像。即,为了保留异常出现时的实时堆栈信息,不应复用异常,每个异常均需单独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一个出来返回以获取正确方法调用堆栈信息。

  

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值