You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JodaTime比较方法违反通用契约异常问题排查咨询

问题描述

在多线程环境中,timeCache可能被其他线程修改,待排序的TimeDTO列表包含50000+元素,getTime()方法返回org.joda.time.DateTime类型对象。使用如下Java方法排序时,偶尔抛出java.lang.IllegalArgumentException: Comparison method violates its general contract!异常:

private Collection<TimeDTO> sortTimes(Choice choice) {

    final List<TimeDTO> times = new ArrayList<>(timeCache.getAll(choice));

    Collections.sort(times, new Comparator<TimeDTO>() {
        @Override
        public int compare(final TimeDTO o1, final TimeDTO o2) {
            if (o1.getTime() == null) {
                return -1;
            }
            if (o2.getTime() == null) {
                return 1;
            }
            return o1.getTime().compareTo(o2.getTime());
        }
    });

    return times;
}

异常栈信息:

Caused by: java.lang.IllegalArgumentException: Comparison method violates its general contract!
    at java.util.TimSort.mergeHi(TimSort.java:899) ~[na:1.8.0_301]
    at java.util.TimSort.mergeAt(TimSort.java:516) ~[na:1.8.0_301]
    at java.util.TimSort.mergeCollapse(TimSort.java:439) ~[na:1.8.0_301]
    at java.util.TimSort.sort(TimSort.java:245) ~[na:1.8.0_301]
    at java.util.Arrays.sort(Arrays.java:1512) ~[na:1.8.0_301]
    at java.util.ArrayList.sort(ArrayList.java:1464) ~[na:1.8.0_301]
    at java.util.Collections.sort(Collections.java:177) ~[na:1.8.0_301]
    at ****.ServiceImpl.sortTimes(ServiceImpl.java:100)
异常原因分析
  • 比较器违反排序契约的核心规则:
    当前比较器逻辑中,如果两个TimeDTO的getTime()都为null,调用compare(o1, o2)会返回-1,调用compare(o2, o1)同样返回-1。这直接违反了比较器的对称性(若a < b则必须b > a)与传递性(若a = b且b = c则a = c)。Java 7及以上版本默认使用的TimSort算法会主动校验排序契约,当列表中存在多个时间为null的元素时,尤其是元素数量超过5万、触发TimSort的合并逻辑时,这种契约违反会被检测到并抛出异常。

  • 多线程环境下的并发修改问题:
    timeCache.getAll(choice)返回的集合在构造ArrayList的过程中,可能被其他线程修改。比如某个TimeDTO的getTime()值在构造列表时是非null,但排序过程中被改为null;或者构造时为null,排序时被改为非null。这种元素状态的并发变更会导致比较过程出现前后矛盾的结果,破坏排序契约,进而触发异常。

内容的提问来源于stack exchange,提问作者Rómeó Nagy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 21:02:43