考虑对JDK的底层堆栈信息进行处理,一种是重写JDK的Throwable,另一种是在原错误堆栈信息上进行“二次加工”。目前这两种方式我都实现了,效果非常好。

这篇文章主要记录对错误堆栈进行“二次加工”的实现过程。

从大量的实际错误日志分析出发:

首先,追根溯源,找到错误是从哪个地方new出来的。

例如
com.jfinal.plugin.activerecord.ActiveRecordException: java.lang.ClassCastException: com.alibaba.druid.sql.visitor.SQLEvalVisitorImpl cannot be cast to com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor
 at com.jfinal.plugin.activerecord.Db.paginate(Db.java:554)
 at com.jfinal.plugin.activerecord.Db.paginate(Db.java:593)
 at com.simple.sqpt.services.FWCXService.doGetHouseInfo(FWCXService.java:172)

那么是在Db.paginate(Db.java:554)这一行new出来的,后面有:
Caused by: java.lang.ClassCastException: com.alibaba.druid.sql.visitor.SQLEvalVisitorImpl cannot be cast to com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor
 at com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock.accept0(SQLServerSelectQueryBlock.java:39)
 at com.alibaba.druid.sql.ast.SQLObjectImpl.accept(SQLObjectImpl.java:40)
说明这个new出来的错误,是包裹了另外一个错误,可能是有new ActiveRecordException(e);然后这个e是一个ClassCastException类型错误
因为只有一个Caused by,可以肯定,这个(ClassCastException) e 是源头,是从:
SQLServerSelectQueryBlock.accept0(SQLServerSelectQueryBlock.java:39)这里new出来的。

应用的栈信息可能夹在中间,比如:

org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is com.ibm.websphere.ce.cm.StaleConnectionException: The Network Adapter could not establish the connectionDSRA0010E: SQL State = 61000, Error Code = 20
  at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:82)
  at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:577)
  at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:641)
  at org.springframework.jdbc.core.JdbcTemplate.queryForInt(JdbcTemplate.java:759)
  at com.proj.webc.persist.framework.BaseDAO.queryForCount(BaseDAO.java:142)
  at com.proj.webc.persist.office.dao.OfficeDAO.queryBackUsersCountByCondition(OfficeDAO.java:734)
  at com.proj.webc.logic.office.OfficeManagerImpl.queryCountOfficeByCondition(OfficeManagerImpl.java:79)
  at com.proj.webc.present.orderquery.action.FrontOrderQueryAction.doAction(FrontOrderQueryAction.java:118)
  at com.proj.webc.framework.BaseAction.execute(BaseAction.java:205)
  at sun.reflect.GeneratedMethodAccessor81.invoke(Unknown Source)
  at java.lang.reflect.Method.invoke(Method.java:600)
  at com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:450)
  at com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:289)

像这种,其实我们只能操纵应用之前的错误信息,应用之后的,超出了我们的管理范围。 比如上面这个例子,在com.proj.**之前的org.springframework.**是我们可以管理的, 但是后面的sun.reflect.**,java.lang.**,com.opensymphony.**都超出了应用的可视范围。 (除非从源头控制,比如com.opensymphony.**的源码,最上层,应该是webContainer,例如websphere下,最外层的栈信息都是com.ibm.**开头)

分析上面的错误信息,我们可以操作的最外层,是 com.proj.webc.framework.BaseAction.execute(BaseAction.java) 我们可以在这个地方做工作,把它管辖之下的错误信息进行整理,例如可以把 org.springframework.**这种信息都过滤掉。

如果是用log工具,我们就有控制权。

综上分析,对于最上层,紧跟着错误信息的地方,只需要追溯到错误new出来之前的前几个轨迹即可。 一般来说,只需要跟踪和new出来错误的那个类在同一个api包之中的,比如上面这个例子, 只需要跟踪到第二行 com.jfinal.plugin.activerecord.Db.paginate(Db.java:593)即可。

对于Caused by,是非常核心的错误出处,一般是在应用之中的,可采取和上面一样的处理方式,如果是调用第三方api抛出的错误,如上面那个例子。 其实捕获栈信息的意义不是很大,但是也可以少量捕捉一些,比如一前一尾。但是尾巴不好判断,所以考虑到性能,只捕捉前面2行就够意思了。后面的话 要逐行判断,如果是本应用的类,则捕捉。

捕捉到最后,是三个点:  ... 39 more 这样,Caused by就处理完成了。如果后面还有Caused by,也用该方法继续捕捉。

综上,其实就一个方法: 检测非\tat开头的字符串,记录其信息。(可设定长度大小,比如小于1000)

对于\tat开头的字符串,判断是否为本应用+特定api的前缀,是则保留。

特殊处理: 保留紧跟着非\tat开头的字符串的2行栈信息,

保留出现本应用+特定api前缀那一行的前3行信息。

算法复杂度,假设有100行,一行比较30次char(用startWith),总共for循环100次,每次比较一个startWith,

每次循环假设还做一个5个if的判断,那么一共比较的次数为500+3000=3500,对CPU来说,应该不成问题。

Java异常处理设计(二)的更多相关文章

  1. Java异常处理设计(一)

    很多次的经验教训,让我不得不重视异常处理.经常遇到的问题如下:1)日志不准确,错误原因难以查明!!2)日志量太大,查找麻烦!!3)哪里需要记录日志,哪里不用记录日志?往往随心所欲!!分析以上问题,深入 ...

  2. Java异常处理设计(三)

    接着上一篇讲. 一个异常日志处理的例子: 抛出异常的地方为: try{ ... ...//省略N行 }catch( Exception e){ throw new RuntimeException ( ...

  3. Java异常处理和设计

    在程序设计中,进行异常处理是非常关键和重要的一部分.一个程序的异常处理框架的好坏直接影响到整个项目的代码质量以及后期维护成本和难度.试想一下,如果一个项目从头到尾没有考虑过异常处理,当程序出错从哪里寻 ...

  4. Java异常处理和设计【转】

    Java异常处理和设计 在程序设计中,进行异常处理是非常关键和重要的一部分.一个程序的异常处理框架的好坏直接影响到整个项目的代码质量以及后期维护成本和难度.试想一下,如果一个项目从头到尾没有考虑过异常 ...

  5. java异常处理的设计

    有一句这样话:一个衡量Java设计师水平和开发团队纪律性的好方法就是读读他们应用程序里的异常处理代码. 本文主要讨论开发Java程序时,如何设计异常处理的代码,如何时抛异常,捕获到了怎么处理,而不是讲 ...

  6. Java秒杀简单设计二:数据库表和Dao层设计

    Java秒杀简单设计二:数据库表Dao层设计 上一篇中搭建springboot项目环境和设计数据库表  https://www.cnblogs.com/taiguyiba/p/9791431.html ...

  7. JAVA 异常处理机制

    主要讲述几点: 一.异常的简介 二.异常处理流程 三.运行时异常和非运行时异常 四.throws和throw关键字 一.异常简介 异常处理是在程序运行之中出现的情况,例如除数为零.异常类(Except ...

  8. java异常处理机制

    本文从Java异常最基本的概念.语法开始讲述了Java异常处理的基本知识,分析了Java异常体系结构,对比Spring的异常处理框 架,阐述了异常处理的基本原则.并且作者提出了自己处理一个大型应用系统 ...

  9. Java 异常处理机制和集合框架

    一.实验目的 掌握面向对象程序设计技术 二.实验环境 1.微型计算机一台 2.WINDOWS操作系统,Java SDK,Eclipse开发环境 三.实验内容 1.Java异常处理机制涉及5个关键字:t ...

随机推荐

  1. (16)The beauty of what we'll never know

    https://www.ted.com/talks/pico_iyer_the_beauty_of_what_we_ll_never_know/transcript 00:13One hot Octo ...

  2. windows下 python2 和python3 共存

    目前我们在国内网站上看到的两者共存的方法就是将其中一个的python.exe重命名.虽说在一定程度上可行,但存在一个重大的隐患,就是修改了名字的那个python对应的pip将无法使用. 下面说一下具体 ...

  3. Effective C++ 随笔(4)

    条款21:必须返回对象时,别妄想返回其reference 例子: Raional类可以执行有理数的一些运算,并且使用heap内存申请 并且其operator*函数为 const Rational&am ...

  4. VB6.0中WinSock控件属性和方法详解

    原文链接:http://liweibird.blog.51cto.com/631764/653134 WinSock控件能够通过UDP协议(用户数据报协议)或TCP协议(数据传输协议)连接到远程的机器 ...

  5. js 上传文件夹

    最近公司做工程项目,实现文件夹上传. 网上找了一天,发现网上很多代码都存在相似问题,最后终于找到了一个符合要求的项目. 工程如下: 这里对项目的文件传输功能做出分析,怎么实现文件夹上传的,如何进行文件 ...

  6. bzoj2002(lct模板)

    #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #inclu ...

  7. 移动端 - APP测试要点

    功能测试 1.运行 1)App安装完成后的试运行,可正常打开软件. 2)App打开测试,是否有加载状态进度提示. 3)App页面间的切换是否流畅,逻辑是否正确. 2.注册 1)同表单编辑页面 2)用户 ...

  8. SSM_CRUD新手练习(3)创建数据库

    在上一节我们已经完成了基本的SSM配置,现在需要创建我们数据库. 我们需要两张表分别为tbl_emp(员工表)和tbl_dedpt(部门表).同时d_id是部门表对应dept_id的外键. 需要注意的 ...

  9. C语言中:static与extern对变量和函数的作用

    1.两者对全局变量 static对全局变量,表示定义一个内部变量 extern对全局变量,表示声明一个外部变量 说明: 1.内部变量:定义的变量只能在本文件中访问,不能被其他文件访问. 2.不同文件中 ...

  10. 保存到Excel文件中

    OLEObject ole_object , ole_workbooks ole_object = CREATE OLEObjectIF ole_object.ConnectToNewObject(& ...