J'ai créé une palette de couleurs contenant un tableau jPanel et un tableau JLabel. Au début, cela a bien fonctionné, mais j’ai ensuite ajouté quelques autres jLabels à JPanel et les ai ajoutés à certains événements. Maintenant, je continue à avoir cette erreur:
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)
J'ai essayé de supprimer tout ce que j'ai fait après la première fois que j'ai eu cette erreur, mais continue à l'obtenir. Lorsque je modifie la présentation de GridLayout par autre chose, l'erreur disparaît mais le code devient inutile. J'ai donc besoin de GridLayout. Lorsque je déplace tout dans ce JPanel vers un autre JPanel, l'erreur disparaît également. Mais lorsque je supprime le premier JPanel, l'erreur revient.
Au fait, le programme fonctionne, mais il n'est pas agréable de continuer à avoir des erreurs ...
Edit: Lorsque j'utilise moins de 225 couleurs, il n'y a pas d'erreur. Je suis vraiment curieux de savoir ce qui se passe. Toute explication serait appréciée ...
Il me semble que vous avez frappé un bug dans le JDK puisque l'erreur semble provenir des classes Swing.
Options:
Définissez la propriété Java.util.Arrays.useLegacyMergeSort
comme true
. Soit en utilisant dans votre code la ligne
System.setProperty("Java.util.Arrays.useLegacyMergeSort", "true");
avant tout code Swing. La première ligne de la méthode main
devrait fonctionner.
Ou en ajoutant
-Djava.util.Arrays.useLegacyMergeSort=true
à vos options de départ (dans la console ou dans les propriétés du projet dans un IDE, un script Ant, etc.)
Mettez à niveau votre JDK et voyez si le problème disparaît
Signaler mes résultats:
-Djava.util.Arrays.useLegacyMergeSort=true
travaux
mais
System.setProperty("Java.util.Arrays.useLegacyMergeSort", "true");
ne marche pas.
C’est parce que dans JDK Arrays.class
static final class LegacyMergeSort {
private static final boolean userRequested = ...
C'est une variable statique qui est définie quand jvm démarre. La définition de la propriété System dans le programme n'aura aucun effet si la classe a été chargée dans jvm.
J'ai surveillé la variable LegacyMergeSort.userRequested et les résultats ont été confirmés par la déclaration ci-dessus.
Update : Le programme doit définir les propriétés système avant que Java.util.Arrays ne soit chargé dans classloader . Sinon, une fois chargé, la définition des propriétés ne sera plus utile en raison du motif mentionné au dessus de.
Assurez-vous que rien d'autre n'est chargé dans Arrays.class:
En mettant le code suivant dans votre programme pour tester:
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));
[Mise à jour] Cette solution ne permet malheureusement pas de résoudre le problème dans tous les cas. Il ne suffit pas de patcher la stratégie par défaut SortingFocusTraversalPolicy .__ du KeyboardFocusManager.
Je recommande de lire la réponse de Robin Loxley ci-dessous, y compris sa mise à jour . [/ Update]
Java.lang.IllegalArgumentException: Comparison method violates its general contract!
at Java.util.TimSort.mergeHi(TimSort.Java:868)
Ce problème est dû à un bogue dans javax.swing.LayoutComparator
.
La classe suivante installe une version corrigée de javax.swing.LayoutComparator
, qui ne viole pas le contrat de Comparator<Component>
. Cette version (ou toute autre version) corrigée de javax.swing.LayoutComparator
devrait être soumise à Oracle par un contributeur Oracle.
package ...;
import Java.awt.Component;
import Java.awt.ComponentOrientation;
import Java.awt.FocusTraversalPolicy;
import Java.awt.KeyboardFocusManager;
import Java.awt.Window;
import Java.lang.reflect.Field;
import Java.util.Comparator;
import Java.util.LinkedList;
import Java.util.ListIterator;
import javax.swing.JRootPane;
import javax.swing.SortingFocusTraversalPolicy;
import javax.swing.UIManager;
/**
* Uses reflection to install a fixed version of {@link javax.swing.LayoutComparator} to solve the
* LayoutFocusTraversalPolicy/TimSort problem.
*
* <p>
* <code>Java.lang.IllegalArgumentException: Comparison method violates its general contract!</code>
* <br/>
* {@code at Java.util.TimSort.mergeHi(TimSort.Java:868)}
* </p>
* <p>
* Usage: call {@code Class.forName(LayoutFocusTraversalPolicyTimSortBugFixer.class.getName())}
* before creating Swing components.
* </p>
*
* @author Burkhard Strauss
* @since Feb 2015
*/
public class LayoutFocusTraversalPolicyTimSortBugFixer
{
static
{
UIManager.getUI(new JRootPane()); // make Swing install the SortingFocusTraversalPolicy
final KeyboardFocusManager keyboardFocusManager = KeyboardFocusManager
.getCurrentKeyboardFocusManager();
final FocusTraversalPolicy focusTraversalPolicy = keyboardFocusManager
.getDefaultFocusTraversalPolicy();
boolean fixed = false;
if (focusTraversalPolicy instanceof SortingFocusTraversalPolicy)
{
try
{
final Field field = SortingFocusTraversalPolicy.class.getDeclaredField("comparator");
final boolean accessible = field.isAccessible();
try
{
field.setAccessible(true);
field.set(focusTraversalPolicy, new LayoutComparator());
fixed = true;
}
finally
{
field.setAccessible(accessible);
}
}
catch (final Exception e)
{
}
}
if (!fixed)
{
Loggers.getLoggerFor(LayoutFocusTraversalPolicyTimSortBugFixer.class).warn("could not fix the bug");
}
}
/**
* Fixed version of {@link javax.swing.LayoutComparator}.
* <p>
* Search for 'bugfix' in the code.
* </p>
*
* @author Burkhard Strauss
* @since Feb 2015
*/
@SuppressWarnings("serial")
private static class LayoutComparator implements Comparator<Component>, Java.io.Serializable
{
private static final int ROW_TOLERANCE = 10;
private boolean horizontal = true;
private boolean leftToRight = true;
@SuppressWarnings("unused")
void setComponentOrientation(final ComponentOrientation orientation)
{
horizontal = orientation.isHorizontal();
leftToRight = orientation.isLeftToRight();
}
@Override
public int compare(Component a, Component b)
{
if (a == b)
{
return 0;
}
// Row/Column algorithm only applies to siblings. If 'a' and 'b'
// aren't siblings, then we need to find their most inferior
// ancestors which share a parent. Compute the ancestory lists for
// each Component and then search from the Window down until the
// hierarchy branches.
if (a.getParent() != b.getParent())
{
final LinkedList<Component> aAncestory = new LinkedList<Component>();
for (; a != null; a = a.getParent())
{
aAncestory.add(a);
if (a instanceof Window)
{
break;
}
}
if (a == null)
{
// 'a' is not part of a Window hierarchy. Can't cope.
throw new ClassCastException();
}
final LinkedList<Component> bAncestory = new LinkedList<Component>();
for (; b != null; b = b.getParent())
{
bAncestory.add(b);
if (b instanceof Window)
{
break;
}
}
if (b == null)
{
// 'b' is not part of a Window hierarchy. Can't cope.
throw new ClassCastException();
}
for (ListIterator<Component> aIter = aAncestory.listIterator(aAncestory.size()), bIter = bAncestory
.listIterator(bAncestory.size());;)
{
if (aIter.hasPrevious())
{
a = aIter.previous();
}
else
{
// a is an ancestor of b
return -1;
}
if (bIter.hasPrevious())
{
b = bIter.previous();
}
else
{
// b is an ancestor of a
return 1;
}
if (a != b)
{
break;
}
}
}
final int ax = a.getX(), ay = a.getY(), bx = b.getX(), by = b.getY();
int zOrder = a.getParent().getComponentZOrder(a) - b.getParent().getComponentZOrder(b);
{
//
// Here is the bugfix:
// Don't return 0 if a != b. This would violate the contract of
// Comparator<Component>.compare().
//
if (zOrder == 0)
{
zOrder = -1;
}
}
if (horizontal)
{
if (leftToRight)
{
// LT - Western Europe (optional for Japanese, Chinese, Korean)
if (Math.abs(ay - by) < ROW_TOLERANCE)
{
return (ax < bx) ? -1 : ((ax > bx) ? 1 : zOrder);
}
else
{
return (ay < by) ? -1 : 1;
}
}
else
{ // !leftToRight
// RT - Middle East (Arabic, Hebrew)
if (Math.abs(ay - by) < ROW_TOLERANCE)
{
return (ax > bx) ? -1 : ((ax < bx) ? 1 : zOrder);
}
else
{
return (ay < by) ? -1 : 1;
}
}
}
else
{ // !horizontal
if (leftToRight)
{
// TL - Mongolian
if (Math.abs(ax - bx) < ROW_TOLERANCE)
{
return (ay < by) ? -1 : ((ay > by) ? 1 : zOrder);
}
else
{
return (ax < bx) ? -1 : 1;
}
}
else
{ // !leftToRight
// TR - Japanese, Chinese, Korean
if (Math.abs(ax - bx) < ROW_TOLERANCE)
{
return (ay < by) ? -1 : ((ay > by) ? 1 : zOrder);
}
else
{
return (ax > bx) ? -1 : 1;
}
}
}
}
}
}
Je viens de rencontrer la même erreur et j'ai passé beaucoup de temps à la localiser. Pour aider les autres utilisateurs de cette erreur, il est important de savoir comment tester TimSort. Les contrôles qui violent le contrat de transitivité et génèrent cette erreur sont profondément ancrés dans l'algorithme et nécessitent un test pour répondre à certains critères avant que ce problème puisse être reproduit.
Une fois que vous remplissez ces deux critères, vous pouvez commencer à tester cet échec.
Une exécution est définie comme un sous-ensemble de la liste où chaque élément est déjà dans l'état ordonné souhaité.
Il ne suffit pas de patcher LayoutComparator comme suggéré ci-dessus. Ce correctif ne fonctionne pas dans mon cas . Le problème a été résolu dans JDK 8 (au moins 8u45) . SortingFocusTraversalPolicy pour utiliser la méthode de tri par fusion héritée.