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

        Attachments

          Issue Links

            Activity

              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: