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

hashCode() implementation for java.awt.SystemColor / java.awt.Color is flawed

XMLWordPrintable

    • generic
    • generic

      SYNOPSIS
      --------
      hashCode() implementation for java.awt.SystemColor / java.awt.Color is flawed

      OPERATING SYSTEM
      ----------------
      All

      FULL JDK VERSION
      ----------------
      All Java 6 releases are affected by the Java 6 issue
      All Java 7 builds are affected by the Java 7 issue

      PROBLEM DESCRIPTION from LICENSEE
      ---------------------------------
      The results of calling hashCode() on the static SystemColor instances defined in the SystemColor class break the hashCode() contract on Java 6, and Java 7, for different reasons on each release.

      In the API documentation for java.lang.Object, the general contract for hashCode() states:

      * Whenever it is invoked on the same object more than once during an
        execution of a Java application, the hashCode method must consistently
        return the same integer, provided no information used in equals
        comparisons on the object is modified. This integer need not remain
        consistent from one execution of an application to another execution
        of the same application.

      * If two objects are equal according to the equals(Object) method, then
        calling the hashCode method on each of the two objects must produce
        the same integer result.

      On Java 6, SystemColor.hashCode() breaks the second part of the contract. Two SystemColor instances can be equal even though their hash codes are different.

      That problem is fixed on Java 7, where the integer returned by SystemColor.hashCode() is identical to the integer returned by SystemColor.getRGB(). Both calls actually invoke the methods in the parent Color class, unlike Java 6 where hashCode() is overridden in the SystemColor class. However, this causes another problem. Consider the following statement in the SystemColor API documentation:

         For systems which support the dynamic update of the system colors
         (when the user changes the colors) the actual RGB values of these
         symbolic colors will also change dynamically.

      Since hashCode() is returning the RGB colour value, and that RGB colour value can change dynamically, it follows that the return value of hashCode() can also change during the execution of a Java application, thus violating part 1 of the hashCode() contract. This is proved by the second testcase provided below.

      REPRODUCTION INSTRUCTIONS - JAVA 6 ISSUE
      ----------------------------------------
      1. Compile and run SystemColorTest1.java (attached)
      2. Observe the following behaviour on Java 6:

         Found equals() / hashCode() contract violation:
         Compared java.awt.SystemColor[i=14] to java.awt.SystemColor[i=1]
         java.awt.SystemColor[i=14] hashcode = 14
         java.awt.SystemColor[i=1] hashcode = 1
         java.awt.SystemColor[i=14] RGB value = -13410648
         java.awt.SystemColor[i=1] RGB value = -13410648

         Test failed!

      3. Observe the following result on Java 7, which represents the expected
         behaviour:

         Test passed!

      REPRODUCTION INSTRUCTIONS - JAVA 7 ISSUE
      ----------------------------------------
      1. Compile and run SystemColorTest2.java (attached)

      2. While the testcase is running, change the colour of the OS desktop
         (for example, on Windows, simply right click the desktop and change
         the setting in Properties->Desktop->Color)

      3. Observe a result similar to the following with Java 7 (the integers
         involved depend on the colours you change to/from):

         hashCode() return value changed from -16777216 to -65536
         Test Failed!

      4. Observer the following result with Java 6 (the expected behaviour):

         Test Passed!


      TESTCASE SOURCE (ATTACHED)
      ------------------------------
      SystemColorTest1 - JDK 6 Issue.
      SystemColorTest2 - JDK 7 Issue.

            Unassigned Unassigned
            dkorbel David Korbel (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Imported:
              Indexed: