Reputation: 52478
This is a tough one. A customer has sent me, via a crash report, this stack trace. It has no mention of my app's classes, so I'm perplexed as to where to start looking.
My app is a commercial desktop app. Crash reports are anonymous, so I can't easily obtain more information about the crash.
EDIT: Some Googling and thread-following makes me conclude that it is a sporadic problem in Java 1.7. Looking for a solution...
How can I proceed in debugging this?
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)
Upvotes: 5
Views: 969
Reputation: 52478
This is a documented bug introduced in Java by Oracle. It has now been fixed.
The workaround I've been using was to set a relevant system property immediately after my app launches:
System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
The issue was fixed in Java 8u40, so the workaround is no longer necessary.
See: https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8048887
Upvotes: 0
Reputation: 432
As per rules of new Comparable Contract given rules must always be true for compareTo function. These rules were introduced in JDK 7 -
The implementor must ensure that sgn(compare(x, y)) ==
-sgn(compare(y, x))
for all x
and y
. (This implies that compare(x, y) must throw an exception if and only if compare(y, x) throws an exception.
The implementor must also ensure that the relation is transitive: ((compare(x, y) > 0, (compare(y, z) > 0))
implies compare(x, z) > 0
Finally, the implementor must ensure that compare(x, y)==0
implies that sgn(compare(x, z)) == sgn(compare(y, z))
for all z.
Now, as obvious as it may seem that these rules will always be abided by, we have many exceptions.
Consider the case - Implementation of compareTo function in code -
return (int) (y - x)
where x & y are double. Let's consider x = 2
, y = 1.6
The values satisfy rules 1 and 2 but for rule 3, consider 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.
Hence, violating the contract.
Upvotes: 0
Reputation: 6901
As pointed out elsewhere, the items in the collection being sorted (which may or may not include your own classes, can't tell from the stack trace) violate the comparison contract.
During a transition from Java 6 to Java 7, the default sorting implementation changed to TimSort. One of the impacts of this is that the new sort is more strict about the comparison contract, so you (or perhaps, Swing) may have been getting away with it for a long time, but no longer.
If you can't fix the problem with the comparison contract, you can roll back to use the Java 6 style sorting by booting your application with the property
-Djava.util.Arrays.useLegacyMergeSort=true
as detailed in the Java 7 release notes, compatibility section.
Upvotes: 3
Reputation: 21793
java.lang.IllegalArgumentException: Comparison method violates its general contract!
I suspect this means that the Comparison method is not a total ordering. As in, it violates one of the three properties ALL sorting methods must have:
1) Reflexivity - if x == y, y == x. If x > y, y < x.
2) Identity: x == x.
3) Transistivity: if x > y and y > z, x > z.
The comparison method needs to be fixed to obey these laws. How to do that will remain to be seen when you look at it :)
Upvotes: 1