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

Arrays.sort may throw IllegalArgumentException when array contains null elements

XMLWordPrintable

      FULL PRODUCT VERSION :
       jdk1.8.0_131

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 6.1.7601]

      A DESCRIPTION OF THE PROBLEM :
      We are getting IllegalArgumentException stating "Comparison Method Violates Its General Contract!".
      Exception is coming as java.util.ComparableTimSort.class tends to give IllegalArgumentException when contract defined in interface Comparable is broken. For java version 1.7 and above this class is being used for sorting.
      Actual issue is in compareTo(T o) method defined in our file as it breaks the contract defined in interface Comparable that is The implementor must ensure  relation is
       transitive: (x.compareTo(y)>0 && y.compareTo(z)>0) implies x.compareTo(z)>0.

      In our case, if the values we are comparing are null,will breaks the transitivity as null compares equal to anything. This is wrong, because it will compare equal to multiple things that are not equal among themselves.

      From end user perspective, it does create a confusion that for the same code violating the compareTo method contract , no exception is thrown in case of smaller arrays (less than 32) but an exception is thrown for larger arrays (>31). It further adds to the confusion that it is not always the case for larger arrays(>31).There should be consistency in the output shown to the user irrespective of array size 32 and above.

      In some cases even though size of the list is greater than 31 , we are not getting the exception for same compareTo method for which contract is broken. So, we are not able to tell when exactly the exception will be thrown. Kindly guide us in this matter.

      Although we know how to resolve this, our main concern is to know why for one list (size>32) we are getting the error but for another list (size>32) , we are not getting the error even though both lists contain null values to be compared and transitive contract is broken for both the lists.

      REGRESSION. Last worked in version 6u45


      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      org.apache.struts.action.EXCEPTION class java.lang.IllegalArgumentException
      Comparison method violates its general contract!
      java.lang.IllegalArgumentException: Comparison method violates its general contract!
      at java.util.ComparableTimSort.mergeHi(ComparableTimSort.java:866)
      at java.util.ComparableTimSort.mergeAt(ComparableTimSort.java:483)
      at java.util.ComparableTimSort.mergeForceCollapse(ComparableTimSort.java:422)
      at java.util.ComparableTimSort.sort(ComparableTimSort.java:222)
      at java.util.Arrays.sort(Arrays.java:1312)
      at java.util.Arrays.sort(Arrays.java:1506)
      at java.util.Vector.sort(Vector.java:1319)
      at java.util.Collections.sort(Collections.java:141)


      REPRODUCIBILITY :
      This bug can be reproduced occasionally.

      ---------- BEGIN SOURCE ----------
          public int compareTo(Object o) {
              if (this == o) {
                  return 0;
              }

              if (o == null) {
                  return 1;
              }
              int result = 0;

              AbcDTO that = (AbcDTO) o;

              Integer contact = getContact();
              Integer thatContact = that.getContact();

              String code= this.code;
              String thatCode = that.Code;

              result = contact.compareTo(thatContact);
              if (result == 0) {
                  if (!TextUtils.isBlank(code)) {//Check if the given string is null or a blank string
                      if (TextUtils.isBlank(thatCode )) {
                          result = 1;
                      } else {
                          result = code.compareTo(thatCode );
                      }
                  } else {
                      result = -1;
                  }
              }
              return result;
          }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      if(contact== null || thatContact==null)
      return 1;

      if(code== null || thatCode==null)
      return 1;

      If we are using above snippet of code to handle then we are getting the sorted result without any issue.


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

              Created:
              Updated:
              Resolved: