Which class throws an IllegalArgumentException when sorting with JRE 1.7?

I was struck by the (apparently notorious) IllegalArgumentException using Collections.sort () in Java7
Thanks to SO, I understand the reason, which is basically (cough) bad code.
The fact is that I cannot reproduce the Exception myself. I did some code searching for the jdk source code and found which class throws this exception. The idea is to create an appropriate test case. Here is the code, by the way, <pride level = "0">

@Override public int compareTo( Symbol other) { if( this.lastUse == 0) { if( other.lastUse != 0) return (int)( -DateMicros.ONE_DAY); } else if( other.lastUse == 0) { return ( int)DateMicros.ONE_DAY; } return ( int)( this.lastUse - other.lastUse); } 

</ pride> On top of that, "lastUse" gets the assigned timestamps in microseconds and milliseconds (yes mixed), which gives an excellent int overflow leak

The real question is:
What values ​​will make this code crash? to get the right test case along the way.

Update with stack trace:

 at java.util.ComparableTimSort.mergeHi(Unknown Source) at java.util.ComparableTimSort.mergeAt(Unknown Source) at java.util.ComparableTimSort.mergeCollapse(Unknown Source) at java.util.ComparableTimSort.sort(Unknown Source) at java.util.ComparableTimSort.sort(Unknown Source) at java.util.Arrays.sort(Unknown Source) at java.util.Collections.sort(Unknown Source) 
+4
source share
3 answers

It's hard to say without looking at the stack itself.

But docs mentions that the method itself may throw an exception.

(optional) if the implementation detects that the natural order of the list items detects a violation of the comparison agreement

Update

It looks like your object does not fulfill the Comparable sequence Comparable :

A natural ordering for a class C is called consistent with equalities if and only if e1.compareTo (e2) == 0 has the same Boolean value as e1.equals (e2) for all e1 and e2 of class C. Note: null is not is an instance of a class, and e.compareTo (null) should throw a NullPointerException, even if e.equals (null) returns false.

+1
source

It seems that the accident was caused by an integer overflow, which, however, should not have happened. This has been identified as a bug, and it also gives you a way.

 http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7075600 

Try this as a temporary fix:

 Adding -Djava.util.Arrays.useLegacyMergeSort=true to my eclipse.ini does seem to have resolved the issue. 

You can find this fix in the same link that I posted.

Also visit this http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6923200 , which was the same message reported before the first link, however it was closed because they were unable to re-create such same problem.

+3
source

From Java SE 7 and JDK 7 Compatibility

Scope: API: Utilities

Summary: Updated sorting behavior for arrays and collections may raise an IllegalArgumentException

Description: The sorting algorithm used by java.util.Arrays.sort and (indirectly) using java.util.Collections.sort been replaced. A new sort implementation may raise an IllegalArgumentException if it detects a Comparable that violates the Comparable contract . The previous implementation silently ignored this situation. If previous behavior is required, you can use the new system property java.util.Arrays.useLegacyMergeSort to restore the previous merge behavior. Incompatibility Pattern: Behavioral

RFE: 6804124

So the correct implementation should look like

  public int compareTo( Symbol other) { if( this.lastUse == other.lastUse) { return 0; } else if( other.lastUse>this.lastUse) { return 1; } return -1; } 

References

+2
source

Source: https://habr.com/ru/post/1441660/


All Articles