Use a unit test below to reproduce this by running the comparator:
Which is copied from Confluence code.
Confluence will throw the following error message:
That basically means that the comparator is not written correctly.
Attached a test class to reproduce the error: ContractViolationTest.java
- on Windows 10,
- java version "1.8.0_111" Java(TM) SE Runtime Environment (build 1.8.0_111-b14), Java HotSpot(TM) Client VM (build 25.111-b14, mixed mode)
- Important: it only breaks if collection size is >= 32
Switching the +1 and -1 return values in the comparator's two if blocks fixes the problem.
Note that this change makes "null key" cases appear before "not-null key" cases in the sorted list. It does not affect the original order of objects where the key is not-null.
Adding this JVM system property fixes the issue:
- TimSort has been introduced in Java 7, it is a stable sort that was designed for relatively expensive comparison operations. Only used for sorting objects, not primitives. Its problematic code path is only reached for collections with size >= 32. See http://stackoverflow.com/questions/4018332/is-java-7-using-tim-sort-for-the-method-arrays-sort
- Exception might be caused by non-transitive comparators: http://stackoverflow.com/questions/8327514/comparison-method-violates-its-general-contract
- Atlassian has seen something similar, too: https://confluence.atlassian.com/fishkb/comparison-method-violates-its-general-contract-387941517.html
- Oracle has open issues related to this, promised to be fixed in Java 9: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=7075600
- See: com.atlassian.confluence.api.impl.service.longtasks.LongTaskFactory#buildStatus