如何使用这个堆栈跟踪在Java中进行调试,而不涉及我自己的类?

如何使用这个堆栈跟踪在Java中进行调试,而不涉及我自己的类?,java,swing,Java,Swing,这是一个艰难的过程。一位客户通过故障报告向我发送了此堆栈跟踪。它没有提到我的应用程序的类,所以我不知道从哪里开始寻找 我的应用程序是一个商业桌面应用程序。坠机报告是匿名的,所以我无法轻易获得更多关于坠机的信息 编辑:一些谷歌搜索和线程跟踪让我得出结论,这是Java1.7中的一个零星问题。正在寻找解决方案 如何继续调试此文件 java.lang.IllegalArgumentException: Comparison method violates its general contract!

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

我的应用程序是一个商业桌面应用程序。坠机报告是匿名的,所以我无法轻易获得更多关于坠机的信息

编辑:一些谷歌搜索和线程跟踪让我得出结论,这是Java1.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)

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

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

1) 自反性-如果x==y,y==x。如果x>y,y 2) 标识:x==x

3) 瞬变性:如果x>y且y>z,则x>z


为了遵守这些规律,需要确定比较方法。如何做到这一点还有待观察:)

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

在从Java6到Java7的转换过程中,默认的排序实现更改为。这样做的一个影响是,新的排序对比较契约更加严格,因此您(或者Swing)可能已经逃避了很长一段时间,但不再是

如果无法解决比较契约的问题,可以通过使用属性启动应用程序,回滚到使用Java6样式的排序

-Djava.util.Arrays.useLegacyMergeSort=true

如Java 7发行说明中所述,.

根据新可比合同的规则,给定的规则必须始终适用于compareTo功能。这些规则在JDK 7中引入-

  • 实施者必须确保
    sgn(比较(x,y))==
    -sgn(比较(y,x))
    用于所有
    x
    y
    。(这意味着当且仅当compare(y,x)引发异常时,compare(x,y)必须引发异常

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

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

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

以代码中compareTo函数的实现为例-

   return (int) (y - x)
x和y是双倍的。让我们考虑<代码> x=2 < /代码>,<代码> y=1.6 < /代码> < /p>

值满足规则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.

因此,违反了合同。

这是Oracle在Java中引入的一个有文档记录的错误。它现在已经被修复

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

System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
该问题已在Java8U40中修复,因此不再需要解决方法


请参阅:

我在Oracle的Java错误跟踪器中发现了一个已知的错误:他们已将其标记为无法复制。这让我很不高兴。“您可以使用新的系统属性
Java.util.Arrays.useLegacyMergeSort
,来恢复以前的mergesort行为。”如果为Swing提供任何
比较器
实现,则问题出在
比较器
实现中。它不会出现在堆栈跟踪中,因为在合并两个运行时检测到错误。原因是运行顺序不正确(由坏的比较器引起)在使用(您的?)比较器后的某个时间检测到。此处存在类似的问题:您可以尝试将
-Djava.util.Arrays.useLegacyMergeSort=true
添加到应用程序参数中,如此处所述。