今天突然有用户反馈各个端都不能使用我们的产品了,出于经验,应该是和最近的一次上线有关,最近的一次上线是升级java版本,1.6->1.8。
按照用户反馈,立刻去线上grep各个机器这个用户的错误日志,未果;跟用户要客户端的本地日志,同样没有发现问题,遂进一步联系用户,开fiddler抓包,看看服务器究竟返回了什么,抓包后,发现返回的是:unknown exception,这下不淡定了,这个异常一般是没有捕获导致的,所以在线上也没有grep到任何详细的日志。
后来,又仔细研究用户日志,发现用户始终在做同一个操作,而且各个端都不能用,然后根据用户刚才的操作,定位到具体的机器上,查看该用户的操作记录,根据时间和处理线程编号,定位到以下错误异常:
Caused by: java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeLo(TimSort.java:777)
at java.util.TimSort.mergeAt(TimSort.java:514)
at java.util.TimSort.mergeCollapse(TimSort.java:441)
at java.util.TimSort.sort(TimSort.java:245)
at java.util.Arrays.sort(Arrays.java:1512)
at java.util.ArrayList.sort(ArrayList.java:1454)
at java.util.Collections.sort(Collections.java:175)
定位到错误,google之后,处理起来就很快了。
**出错原因:**JDK7以后的版本中排序的Collections.Sort排序算法改成了TimSort,这个算法要求,如果两个值是相等的,那么compare方法需要返回0,否则可能会在排序时抛错,而JDK6是没有这个限制的。
另外,由于用户操作是带有事务的,在事务的最后,有个排序,排序出错后,事务回滚,导致操作失败,所以日志中看到日志是用户在做同一个操作,代码中对这个异常没有进行捕获打印详细信息,所以很难定位。
这个问题在测试的时候没有反应出来,线上也是小概率复现
搜了所有的项目代码,找到相关的代码,进行了修改,联系用户,各个端均恢复正常。
关于TimSort的详细信息,可以参考这个: http://blog.2baxb.me/archives/993
来源:oschina
链接:https://my.oschina.net/u/2291281/blog/724526