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

sun.reflect.generics.reflectiveObjects.TypeVariableImpl does not honor equals

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: P3
    • Resolution: Not an Issue
    • Affects Version/s: 7u51
    • Fix Version/s: None
    • Component/s: core-libs
    • Labels:

      Description

      FULL PRODUCT VERSION :
      Java(TM) SE Runtime Environment (build 1.7.0_51-b13)
      Java HotSpot(TM) 64-Bit Server VM (build 24.51-b03, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Windows 7 Enterprise

      A DESCRIPTION OF THE PROBLEM :
      sun.reflect.generics.reflectiveObjects.TypeVariableImpl does not honor equals in the same way that it did in update 45. It now checks the parameter to the equals method to ensure that it is an instance of TypeVariableImpl. I've attached a simple JUNIT 4 test that reproduces this bug.

      REGRESSION. Last worked in version 7u45

      ADDITIONAL REGRESSION INFORMATION:
      sun.reflect.generics.reflectiveObjects.TypeVariableImpl#equals now checks to make sure that the value passed in is of exactly the same class. This was not the case in update 45 and has broken a significant portion of our application.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Subclass java.lang.reflect.TypeVariable and attempt to compare with an instance of sun.reflect.generics.reflectiveObjects.TypeVariableImpl were both objects return the same generic declaration and name. This method will return true subclass.equals(TypeVariableImpl) but false for TypeVariableImpl.equals(subclass).

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The equals method should return true in both cases.
      ACTUAL -
      The equals method should returns true in only 1 case.

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      There is no associated error message.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      package test;

      import java.lang.reflect.GenericDeclaration;
      import java.lang.reflect.Type;
      import java.lang.reflect.TypeVariable;
      import org.hamcrest.core.Is;
      import org.junit.Assert;
      import org.junit.Test;

      public class BugTest {

      // -------------------------- OTHER METHODS --------------------------

      /**
       * This tests a brutal bug in Java 7 update 51.
       */
      @Test
      public void testEquals() throws NoSuchMethodException {
      Type actualType = A.class.getTypeParameters()[0];
      Type expectedType = new TypeVariableImplementation<>(A.class, "Y");

      Assert.assertThat(actualType, Is.is(expectedType));
      Assert.assertThat(expectedType, Is.is(actualType));
      }

      // -------------------------- INNER CLASSES --------------------------

      interface A<Y> {

      // -------------------------- OTHER METHODS --------------------------

      Y getY();

      }

      private static class TypeVariableImplementation<GenericDeclarationType extends GenericDeclaration>
      implements TypeVariable<GenericDeclarationType> {

      // ------------------------------ FIELDS ------------------------------

      private Type[] bounds;

      private GenericDeclarationType declaration;

      private String name;

      // --------------------------- CONSTRUCTORS ---------------------------

      TypeVariableImplementation(GenericDeclarationType declaration, String name, Type... bounds) {
      this.bounds = bounds.clone();
      this.declaration = declaration;
      this.name = name;
      }

      // --------------------- GETTER / SETTER METHODS ---------------------

      @Override
      public String getName() {
      return name;
      }

      // ------------------------ CANONICAL METHODS ------------------------

      @Override
      public boolean equals(Object value) {
      return value instanceof TypeVariable && name.equals(((TypeVariable<?>) value).getName()) &&
      declaration.equals(((TypeVariable<?>) value).getGenericDeclaration());
      }

      @Override
      public int hashCode() {
      return declaration.hashCode() ^ name.hashCode();
      }

      @Override
      public String toString() {
      return name;
      }

      // ------------------------ INTERFACE METHODS ------------------------

      // --------------------- Interface TypeVariable ---------------------

      @Override
      public Type[] getBounds() {
      return bounds.clone();
      }

      @Override
      public GenericDeclarationType getGenericDeclaration() {
      return declaration;
      }

      }

      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Our only work around is to check for instances of TypeVariableImpl and flip the equals comparison if the TypVariable instance would appear on the left hand side.

      SUPPORT :
      YES

        Issue Links

          Activity

          Hide
          jfranck Joel Borggrén-Franck added a comment -
          This is indeed intended. I'm closing this as not an issue, is there something that I should do with the original web bug report (which was good)?
          Show
          jfranck Joel Borggrén-Franck added a comment - This is indeed intended. I'm closing this as not an issue, is there something that I should do with the original web bug report (which was good)?
          Hide
          darcy Joe Darcy added a comment -
          Side-effect of changes made in JDK-8023301.
          Show
          darcy Joe Darcy added a comment - Side-effect of changes made in JDK-8023301.

            People

            • Assignee:
              jfranck Joel Borggrén-Franck
              Reporter:
              webbuggrp Webbug Group
            • Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: