Hello,

Please review the changes to address:

    JDK-8224012: AnnotatedType implementations of hashCode() lead to StackOverflowError
    http://cr.openjdk.java.net/~darcy/8224012.1/

As discussed in the JBS entry, this is a follow-up issue to fix an implementation flaw in JDK-8058202: "AnnotatedType implementations don't override toString(), equals(), hashCode()".

In brief, the equals/hashCode methods in the AnnotatedTypeBaseImpl classes are updated to avoid possible circularities  in their calling structure. As described in more detail below, a comparison is made against analogous implementation types in the sun.reflect.generics.reflectiveObjects package (src/java.base/share/classes/sun/reflect/generics/reflectiveObjects).

A brief summary for some additional context, the original core reflection had various "getFoo" methods in java.lang.Class and the classes in the classes of the java.lang.reflect package. In JDK 5.0, many of these methods had a "getGenericFoo" sibling method added to preserve behavioral compatibility of the original method while providing access to information about generic declarations. In JDK 8, "getAnnotatedFoo" methods were added, as new sibling methods to support type annotations, alongside the existing getFoo and getGenericFoo methods. Semantically, the getAnnotatedfoo methods are "getGenericAnnotatedFoo, but (fortunately) that verbose naming convention was not chosen. A family of AnnoatedBar classes was also added in JDK 8 to allow annotation on interior structures to be modeled, such as a method returning "Set<List<@Quux String>>".

Some notes in the implementation, the hierarchy of annotated type implementation classes is housed in src/java.base/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java. The nested classes are subtypes of AnnotatedTypeBaseImpl. The building blocks of equals and hashCode in that parent type examine the underlying type, annotations, and (possibly null) owner type.

The four subtypes and the information they examine in their equals/hashCode methods:

    AnnotatedArrayType: base information + component type;
        GenericArrayTypeImpl.java compares component type

    AnnotatedParameterizedType: base information + actual type arguments;
        ParameterizedTypeImpl.java compares owner type, raw type, and actual type arguments

    AnnotatedTypeVariable: base information (*changed to omit checking of bounds*);
        TypeVariableImpl.java compares generic declaration and name

    AnnotatedWildcardType: base information + upper bounds + lower bounds;
        WildcardTypeImpl.java compares upper bounds and lower bounds

The newly added test cases quickly stackoverflow when run against the old implementation.

Thanks,

-Joe

Reply via email to