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

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

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

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

1.问题代码

a)自定义异常定义

  1. package demo.bce;  
  2. public class MyException extends RuntimeException {  
  3.     private static final long serialVersionUID = -3802919537257556719L;  
  4.     private String id;  
  5.     public MyException(String id) {  
  6.        super();  
  7.        this.id = id;  
  8.     }  
  9.     public String getId() {  
  10.        return id;  
  11.     }  
  12.     public void setId(String id) {  
  13.        this.id = id;  
  14.     }  
  15.     @SuppressWarnings("unused")  
  16.     private MyException() {  
  17.     }  

b)自定义异常常量

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

c)测试代码

package demo.bce;

  1. public class MyMain {  
  2.     public static void main(String[] args) {  
  3.        testx();  
  4.     }  
  5.     // ///  
  6.     private static void testx() {  
  7.        try {  
  8.            x11();  
  9.        } catch (Exception e) {  
  10.            e.printStackTrace();  
  11.        }  
  12.        try {  
  13.            x12();  
  14.        } catch (Exception e) {  
  15.            e.printStackTrace();  
  16.        }  
  17.        try {  
  18.            x21();  
  19.        } catch (Exception e) {  
  20.            e.printStackTrace();  
  21.        }  
  22.        try {  
  23.            x22();  
  24.        } catch (Exception e) {  
  25.            e.printStackTrace();  
  26.        }  
  27.     }  
  28.     private static void x11() {  
  29.        throw MyExceptionContext.x1;  
  30.     }  
  31.     private static void x12() {  
  32.        throw MyExceptionContext.x2;  
  33.     }  
  34.     private static void x21() {  
  35.        throw MyExceptionContext.x1;  
  36.     }  
  37.     private static void x22() {  
  38.        throw MyExceptionContext.x2;  
  39.     }  

d)测试结果

  1. demo.bce.MyException  
  2. at demo.bce.MyExceptionContext.<clinit>(MyExceptionContext.java:7)  
  3. at demo.bce.MyMain.x11(MyMain.java:36)  
  4. at demo.bce.MyMain.testx(MyMain.java:14)  
  5. at demo.bce.MyMain.main(MyMain.java:7)  
  6. demo.bce.MyException  
  7. at demo.bce.MyExceptionContext.<clinit>(MyExceptionContext.java:8)  
  8. at demo.bce.MyMain.x11(MyMain.java:36)  
  9. at demo.bce.MyMain.testx(MyMain.java:14)  
  10. at demo.bce.MyMain.main(MyMain.java:7)  
  11. demo.bce.MyException  
  12. at demo.bce.MyExceptionContext.<clinit>(MyExceptionContext.java:7)  
  13. at demo.bce.MyMain.x11(MyMain.java:36)  
  14. at demo.bce.MyMain.testx(MyMain.java:14)  
  15. at demo.bce.MyMain.main(MyMain.java:7)  
  16. demo.bce.MyException  
  17. at demo.bce.MyExceptionContext.<clinit>(MyExceptionContext.java:8)  
  18. at demo.bce.MyMain.x11(MyMain.java:36)  
  19. at demo.bce.MyMain.testx(MyMain.java:14)  
  20. at demo.bce.MyMain.main(MyMain.java:7) 

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

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

2.代码分析和猜想

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

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

3.简单总结

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

原文链接:http://jekiy.iteye.com/blog/1318670

【编辑推荐】

  1. 解读Java环境变量配置
  2. Java精确截取字符串
  3. Java I/O系统基础知识
  4. Java 远程文件对接
  5. Java字符编码根本原理
责任编辑:林师授 来源: jekiy的博客
相关推荐

2020-07-08 07:50:50

OOM虚拟机Java

2023-11-15 17:23:30

测试软件开发

2021-06-07 09:37:05

异常Bug排查

2011-04-01 10:55:29

OSPFDebug

2014-11-10 09:42:59

JVM线程堆栈

2023-09-17 23:23:14

Java异常堆栈

2023-03-28 07:08:09

RocketMQ消费者堆栈

2021-01-28 09:34:08

解密密钥取证分析

2021-02-25 08:40:19

Java异常分类异常防护

2021-07-04 22:29:12

MySQL死锁云日志

2021-03-18 10:01:06

Java编译异常运行异常

2022-07-27 11:45:43

iOS苹果系统

2023-03-01 09:07:44

前端监控异常

2020-10-05 21:33:15

隐私数据匿名数据安全

2011-06-14 16:05:31

BUG流程

2010-03-19 14:52:31

Cisco三层交换机

2018-04-19 08:40:37

OracleJOB异常中断

2021-06-05 23:41:47

NET异常 HttpClient

2021-04-13 12:55:06

SpringMVC解析器接口

2021-02-20 16:03:10

程序员bug测试
点赞
收藏

51CTO技术栈公众号