前言自己开发这么多年,遇到的BUG数不胜数。但是再复杂的bug,只要仔细研究代码,加上debug,总能找到原因。但是最近在公司遇到了这个bug。这个bug乍一看很简单,其实很邪恶。有一段时间,我什至无法理解。在几天的时间内,复发的可能性非常低。几乎不可能捕捉到任何踪迹。所以这篇文章非常真实的记录了这个bug的发现和排查的全过程。起因是之前有同事提出请求,提交测试。当测试同事测试到一半的时候。发现后台报错com.alibaba.fastjson.JSONException:cannotcasttoString,value:{"code":"00","msg":"success","data":{这里是正确的数据}}在com.alibaba.fastjson.util.TypeUtils.castToInt(TypeUtils.java:564)~[fastjson-1.2.29.jar:na]在com.alibaba.fastjson.serializer.IntegerCodec.deserialze(IntegerCodec.java:89)~[fastjson-1.2.29.jar:na]一看就知道这个错误很简单,就是fastjson转换类型的错误。收到的json与要转换的类型不匹配。基本上查一下代码,一眼就能解决。结果同事看了一会,也没发现什么问题。然后远程在测试环境运行debug,设置断点准备调试,测试同事操作一下,又好了。然后解除断点,正常运行。过了一会儿,又出现了同样的错误。继续下断点,还是正常的。这个现象让同事们有些摸不着头脑。我在群里看到这个,觉得很有意思,结果却要看看不看。这他妈到底是什么?.我接过它并查看了代码,从我最初的样子来看它完全没问题。我简化了代码并处理了一些伪代码,如下:log.info("执行结果为:{}",json);T结果=JSON.parseObject(json,c);返回结果;调用时:LuaResultresult=executeLua("xxxx",LuaResult.class,args);而返回对象的泛型T是一个LuaResult对象,其结构也很简单:publicclassLuaResult{protectedStringcode;受保护的字符串消息;受保护的T数据;...}根据打印出来的json结果,返回的数据是正确的结果,完全符合LuaResult对象的结构。虽然调用的时候没有泛型,但是由于之前的代码没有使用到LuaResult中的数据,所以解析之后还是保留了JsonObject的类型。从运营的角度来看,这完全没问题。同样的数据我也用本地的main方法运行,也能正常解析。我什至尝试了多次本地循环解析和多线程解析,都没有问题。那为什么偶尔一到服务器环境就报错呢?我也决定远程调试,我不相信会有薛定谔的bug。我远程设置断点,测试同事开始做业务,一切完全正常。于是我把断点去掉了,没过多久,测试同事给我发来了报错的截图。一切真的和以前的同事一样。..现在我也是一头雾水,这么简单的报错,看不出问题就好了,调试不了??而日志返回的json字符串是完全正常的业务返回数据。太妖孽了排错(1)首先确定返回的数据是完全正确的,在打印log的时候可以看出来。没有低级错误,json不匹配返回类型。问题很明显,是fastjson的解析问题,而且项目使用的fastjson版本比较老,1.2.29版本。但是问题在哪里呢?是一个简单的错误,但是当数据和结构完全正确的时候,偶尔的报错就很奇怪了。而且不相信调试的时候就恢复正常了,正常运行的时候还会出问题。而在接下来的步骤中,这个bug似乎消失了,无论是debug启动还是正常启动,都不会再出现了。看到这里,肯定有人会说这不容易。换个json解析框架,或者升级fastjson。至于换框架,私下和同事商量过改用jackson。首先,系统中有很多地方需要改,其次,即使改了,问题也不会再出现了。但就问题而言,无异于绕过,没有真正正面解决。我对这个错误的根源非常感兴趣。所以我不打算改变它,只是面对它。对于fastjson的升级,其实也有猜测是fastjson的一些bug导致的。但是你得提供证据,否则即使升级后没有复发,也不能证明是因为升级了fastjson而修复的,因为这个bug是极其偶发的。也就是说,你还是要找到问题的根本原因。仅靠长期观察无法证明是否修复。最后一次偶然的机会,终于在debug中抓到了一个断点。这也说明不存在薛定谔的虫子,至少我在观察的时候能捕捉到。断点在如下位置(部分业务数据做了一些改动)//json为:{"code":"00","msg":"success","data":{"xxx":21,"yyy":5}}//c是LuaResult.classTresut=JSON.parseObject(json,c);使用IDEA的Evaluate工具查看执行结果然后继续重复执行。在按了几十次回车后,终于报错了:Thisisveryweird.有没有,一样的数据,一样的代码。执行几十次后出现错误。但是问题一定出在fastjson这边。下一步就是破解问题的根源。为了抓住这个原因,我真的舍不得马上升级。排错(2)之前提到我在调用的时候没有加泛型,所以抱着试一试的想法在这次调用中加了泛型,把参数换成了TypeReferenceLuaResult