Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8234482

timsort failure with exception Comparison method violates its general contract

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Not an Issue
    • Icon: P4 P4
    • None
    • 12
    • core-libs

      ADDITIONAL SYSTEM INFORMATION :
      Found this error with antique tomcat 4 and jdk1.8.0_111
      Upgraded to tomcat 9 and jdk-12.0.2
      Same error.


      A DESCRIPTION OF THE PROBLEM :
      This bug does NOT occur in
      winxp
           jdk1.6.0_21
      It DOES occur in
      win7
           jdk1.8.0_111
           jdk-12.0.2

      The problem is in timsort that fails to sort a Vector with 143
      elements that are comparable.
      Here a trace fragment from deep down a tomcat web server:

       java.lang.IllegalArgumentException: Comparison method violates its general contract!
      at java.base/java.util.ComparableTimSort.mergeLo(ComparableTimSort.java:748)
      at java.base/java.util.ComparableTimSort.mergeAt(ComparableTimSort.java:485)
      at java.base/java.util.ComparableTimSort.mergeForceCollapse(ComparableTimSort.java:426)
      at java.base/java.util.ComparableTimSort.sort(ComparableTimSort.java:222)
      at java.base/java.util.Arrays.sort(Arrays.java:1316)
      at java.base/java.util.Arrays.sort(Arrays.java:1510)
      at java.base/java.util.Vector.sort(Vector.java:1412)
      at java.base/java.util.Collections.sort(Collections.java:145)
      at edit.Simulation.foo(Simulation.java:474)

      Replacing:
             Collections.sort(diseases);
      by an ad hoc insertion sorter:
             sortd(diseases); // replacement
      fixes this bug.
      [ the insertion sorter:
          static Vector sortd(Vector<DiseaseInst> di) {
      // simple insertionsort
      int s = di.size();
      if ( s <= 1 ) return di;
      for ( int i = 1; i < s; i++ ) sortd1(di, i);
      return di;
          } // end sortd
          static void sortd1(Vector<DiseaseInst> di, int i) {
      DiseaseInst dii = di.elementAt(i);
      for ( int j = i - 1; 0 <= j; j-- ) {
      DiseaseInst dij = di.elementAt(j);
      if ( dij.compareTo(dii) <= 0 ) {
      di.set(j+1, dii);
      return;
      } else di.set(j+1, dij);
      }
      di.set(0, dii);
          } // end sortd1
      ]
      Here the comparator of DiseaseInst:
        public int compareTo(Object o) {
          int i = inSymptoms.size();
          float rate = rate();
          DiseaseInst di2 = this;
          try { di2 = (DiseaseInst) o; } catch (ClassCastException ignore) {}
          float acceptanceRate2 = di2.getAcceptanceRate();
          int i2 = di2.getInSymptoms().size();
          float rate2 = di2.rate();

          if ( i == i2 ) {
      if ( acceptanceRate2 < acceptanceRate ) return 1;
      if ( acceptanceRate < acceptanceRate2 ) return -1;
      if ( rate2 < rate ) return -1;
      if ( rate < rate2 ) return 1;
      return 0;
          }
          if ( rate2 < rate ) return -1;
          if ( rate < rate2 ) return 1;
          // rate == rate2
          if ( i2 < i ) return -1;
          if ( i < i2 ) return 1;
          if ( acceptanceRate2 < acceptanceRate ) return -1;
          if ( acceptanceRate < acceptanceRate2 ) return 1;
          return 0;
        } // end compareTo




      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Sorry/ I have spend two days on this error that happens in a 5mb servlet source.
      I am not able to recode this stuff.
      The trace may help you ...
      [[ I do remember that this is the 2nd time there is a problem with timsort ]]


      ACTUAL -
      See the trace

      ---------- BEGIN SOURCE ----------
      sorry ...
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      See above ... but that works only for small arrays ...

      FREQUENCY : always


            smarks Stuart Marks
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated:
              Resolved: