论检查Bug看class文件的重要性
说出来真的老丢人了家人们,困扰我将近一周的Bug终于被我找到原因了,作为一个6年老程序员,我进行自我检讨
码农1号:“啥情况就丢老人了,说出来让俺们听听。。。”
码农2号:“妈呀,赶紧说啊,别卖关子了。“
。。。
事情的经过是这样的
需求是:
资料数据核查统计,每天输出问题清单和统计报表,同时需要支持查询2周以内的历史数据设计原则是:
一张表记录问题清单,以日期作为区分
一张表记录统计报表,同样以日期作为区分测试结果:
代码编写完成,第一天本地测试通过,线上测试通过。
第二天,发现问题清单是没问题的,但统计结果却有部分数据不正确,会出现比实际数值大或小的情况,线上重复执行该方法,仍任是错误的结果,但是结果没有变动。
再次本地执行,数据又恢复正常,再次服务器执行,数据又出现错误。
期间修改过代码中的sql执行顺序,重启服务,发现执行正常了,代码回滚后,执行居然也是正常的。
次日又会出现同样的问题。。。分析原因:
1、已经确认的是,数据库、JDK、代码完全一样。
2、难道是线程问题?不应该啊,我用的是单线程。
3、别人也在同时操作这张表?不可能,我们组就这几个人,只有我一个人操作,而且没有其他任何地方涉及到这张表。
4、难道是缓存的问题?任务是每天执行一次,服务器每晚都会重启,不应该有缓存才对。
5、玄学?拉倒吧,我们组长说了一句话”往往这种问题,应该都是很小的问题导致的。“
那到底是什么原因导致在服务器执行统计结果不正确呢
- 难道真的是缓存?
对比一下数据,妈呀,今天的统计结果真的是昨天的问题清单,昨天统计结果是前天的问题清单。这果然是缓存的问题啊 - 不对不对,每天重启,不应是缓存,那就是sql写的有问题,时间取错了?
再次确认,时间取的就是当天日期,甚至还把日期字符串打印到日志中去了。 - 反正已经确认统计结果是前一天的数据了,那就从这里下手,实在不行,要不咱打开class文件看看?看看class文件中是不是哪里编译的有问题?
真是不看不知道,一看吓一跳,我这个类的无参构造居然做了这种事。。。。。。
那Java文件怎么写的呢?
好了,看到这里相信大家也知道问题出在哪里了,在服务启动容器加载的时候,我的today变量的值就已经确定了,即使到了第二天,这个today的值还是前一天的时间,所以每天晚上9点的服务重启后,第二天任务执行的时候,用的还是昨天的日期,所以才会出现统计的是前一天的数据的情况。
解决办法和心得
- 类的成员方法,特别涉及到日期之类的,不要在声明的时候赋值,什么时候用,什么时候赋值最稳妥
- 实在找不出问题在哪,要多看看对应的class文件,看看编译后的代码会不会和你的思路不同。
- 常看看class代码,有助于我们快速的发现bug的出现原因。
- 确实有些问题是我们比较容易忽略的,有些你认为的玄学的问题,往往都是一些不起眼但又很重要的地方犯的错。
学会记错,激励自己,加油,做最好的自己。