“比较方法违反了其总合同!” - TimSort和GridLayout

2022-09-01 05:06:51

我制作了一个带有jPanel和JLabel数组的调色板。起初它运行良好,但后来我从JPanel中放入了一些其他jLabels,并添加了一些事件。现在我一直得到这个错误:

Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeLo(TimSort.java:747)
at java.util.TimSort.mergeAt(TimSort.java:483)
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.SortingFocusTraversalPolicy.getDefaultComponent(SortingFocusTraversalPolicy.java:515)
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.SequencedEvent.dispatch(SequencedEvent.java:116)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:721)
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:244)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:163)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:147)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:139)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:97)

我试图删除我第一次得到这个错误后所做的一切,但仍然继续得到它。当我将布局从GridLayout更改为其他任何内容时,错误就会消失,但代码变得无用。所以我需要GridLayout。当我将该JPanel中的所有内容移动到另一个JPanel时,错误也会消失。但是当我删除第一个JPanel时,错误又回来了。

顺便说一句,该程序可以正常工作,但是不断出现错误并不令人愉快......

编辑:当我使用少于225种颜色时,没有错误。我真的很好奇发生了什么。任何解释将不胜感激...


答案 1

在我看来,你在JDK中遇到了一个错误,因为错误似乎来自Swing类。

选项:

  1. 将属性定义为 。在代码中使用行java.util.Arrays.useLegacyMergeSorttrue

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

    在任何 Swing 代码之前。因为方法中的第一行应该有效。main

    或添加

    -Djava.util.Arrays.useLegacyMergeSort=true
    

    添加到启动选项(在控制台中,或在 IDE、Ant 脚本等的项目属性中)

  2. 升级您的JDK,看看问题是否消失

  3. 降级到 Java 6

答案 2

报告我的发现:

-Djava.util.Arrays.useLegacyMergeSort=true

工程

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

不起作用。

这是因为在JDK数组中.class

 static final class LegacyMergeSort {
    private static final boolean userRequested = ...

它是一个静态变量,在 jvm 启动时定义。如果已将类加载到 jvm 中,则在程序中设置 System 属性将不起作用。

我正在监视LegacyMergeSort.userRequested变量,并且上述声明证实了调查结果。

更新:在将 java.util.Arrays 加载到类加载器之前,程序必须设置系统属性。否则,一旦加载,由于上述原因,设置属性将毫无用处。

确保没有其他已加载的数组.class:

通过将以下代码放入程序中进行测试:

    java.lang.reflect.Method m = ClassLoader.class.getDeclaredMethod("findLoadedClass", new Class[] { String.class });
    m.setAccessible(true);
    ClassLoader cl = ClassLoader.getSystemClassLoader();
    Object test1 = m.invoke(cl, "java.util.Arrays");
    System.out.println("test1 loaded? ->" + (test1 != null));

推荐