5

这是困难的一个。一位客户通过崩溃报告向我发送了此堆栈跟踪。它没有提到我的应用程序的类,所以我很困惑从哪里开始寻找。

我的应用程序是一个商业桌面应用程序。崩溃报告是匿名的,因此我无法轻松获得有关崩溃的更多信息。

编辑:一些谷歌搜索和线程跟踪让我得出结论,这是 Java 1.7 中的零星问题。正在寻找解决方案...

我该如何继续调试呢?

java.lang.IllegalArgumentException: Comparison method violates its general contract!
        at java.util.TimSort.mergeHi(TimSort.java:868)
        at java.util.TimSort.mergeAt(TimSort.java:485)
        at java.util.TimSort.mergeCollapse(TimSort.java:410)
        at java.util.TimSort.sort(TimSort.java:214)
        at java.util.TimSort.sort(TimSort.java:173)
        at java.util.Arrays.sort(Arrays.java:659)
        at java.util.Collections.sort(Collections.java:217)
        at javax.swing.SortingFocusTraversalPolicy.enumerateAndSortCycle(SortingFocusTraversalPolicy.java:136)
        at javax.swing.SortingFocusTraversalPolicy.getFocusTraversalCycle(SortingFocusTraversalPolicy.java:110)
        at javax.swing.SortingFocusTraversalPolicy.getFirstComponent(SortingFocusTraversalPolicy.java:435)
        at javax.swing.LayoutFocusTraversalPolicy.getFirstComponent(LayoutFocusTraversalPolicy.java:166)
        at javax.swing.DefaultFocusManager.getFirstComponent(DefaultFocusManager.java:120)
        at javax.swing.LegacyGlueFocusTraversalPolicy.getFirstComponent(LegacyGlueFocusTraversalPolicy.java:132)
        at javax.swing.LegacyGlueFocusTraversalPolicy.getDefaultComponent(LegacyGlueFocusTraversalPolicy.java:150)
        at java.awt.FocusTraversalPolicy.getInitialComponent(FocusTraversalPolicy.java:169)
        at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:380)
        at java.awt.Component.dispatchEventImpl(Component.java:4731)
        at java.awt.Container.dispatchEventImpl(Container.java:2287)
        at java.awt.Window.dispatchEventImpl(Window.java:2719)
        at java.awt.Component.dispatchEvent(Component.java:4687)
        at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:723)
        at java.awt.EventQueue.access$200(EventQueue.java:103)
        at java.awt.EventQueue$3.run(EventQueue.java:682)
        at java.awt.EventQueue$3.run(EventQueue.java:680)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
        at java.awt.EventQueue$4.run(EventQueue.java:696)
        at java.awt.EventQueue$4.run(EventQueue.java:694)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:693)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
        at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)
4

4 回答 4

3

正如在其他地方指出的那样,正在排序的集合中的项目(可能包括也可能不包括您自己的类,无法从堆栈跟踪中看出)违反了比较合同。

在从 Java 6 到 Java 7 的过渡期间,默认排序实现更改为TimSort。这样做的影响之一是新的排序对比较契约更加严格,所以你(或者也许是 Swing)可能已经很久没有使用它了,但不再是了。

如果您无法解决比较合约的问题,您可以通过使用属性启动应用程序来回滚以使用 Java 6 样式排序

-Djava.util.Arrays.useLegacyMergeSort=true

如 Java 7 发行说明的兼容性部分中所述。

于 2013-01-29T16:40:50.790 回答
1

java.lang.IllegalArgumentException:比较方法违反了它的一般约定!

我怀疑这意味着比较方法不是总排序。如,它违反了所有排序方法必须具有的三个属性之一:

1) 自反性 - 如果 x == y, y == x。如果 x > y,则 y < x。

2)身份:x == x。

3) 传递性:如果 x > y 且 y > z,则 x > z。

需要固定比较方法以遵守这些规律。当您查看它时,如何做到这一点还有待观察:)

于 2013-01-22T05:35:27.027 回答
0

根据新可比合同的规则,给定规则对于 compareTo 函数必须始终为真。这些规则是在 JDK 7 中引入的——

  • 实施者必须确保sgn(compare(x, y)) == -sgn(compare(y, x))所有xy. (这意味着当且仅当 compare(y, x) 抛出异常时 compare(x, y) 必须抛出异常。

    • 实现者还必须确保关系是可传递的:((compare(x, y) > 0, (compare(y, z) > 0))意味着 compare(x, z) > 0

    • 最后,实现者必须确保这compare(x, y)==0意味着sgn(compare(x, z)) == sgn(compare(y, z))所有 z。

现在,尽管这些规则似乎总是会得到遵守,但我们有很多例外。

考虑案例 - 在代码中实现 compareTo 函数 -

   return (int) (y - x)

其中 x & y 是双倍的。让我们考虑一下x = 2y = 1.6

这些值满足规则 1 和 2,但对于规则 3,请考虑z = 2.4

compare(x,y) = int(1.6-2)   = int(-0.4) = 0
compare(x,z) = int(2.4-2)   = int(0.4) = 0
compare(y,z) = int(2.4-1.6) = int(0.8) = 1.

因此,违反了合同。

于 2018-11-26T03:10:54.937 回答
0

这是 Oracle 在 Java 中引入的一个已记录的错误。现在已经修复了。

我一直在使用的解决方法是在我的应用启动后立即设置相关的系统属性:

System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");

该问题已在 Java 8u40 中修复,因此不再需要解决方法。

请参阅:https ://bugs.java.com/bugdatabase/view_bug.do?bug_id=8048887

于 2018-11-27T08:47:15.013 回答