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

Copy method annotations and parameter annotations to synthetic bridge methods

    XMLWordPrintable

Details

    • b94
    • x86
    • windows_xp
    • Verified

    Backports

      Description

        A DESCRIPTION OF THE REQUEST :
        When a class extends a generic classes or implements a generic interface, synthetic method may be generated to bridge between the method taking specific parameters/return and the one of the super-class/interface which is defined with Objects, because of erasure. A bridge method redirects the call to the actual method, according to Java Language Specification. However the bridge method lacks the annotations defined for the original method and its parameters.

        JUSTIFICATION :
        The problem arises when trying to retrieve annotations of such a method at run-time. Since it's impossible to find out reliably what classes substitute the generic parameters, we don't know what parameter to send to getMethod(...) in order to receive the correct method back. When sending Object.class (while generic parameter is a different class) getMethod will return the bridge method, which won't have the information about the original method annotations.

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        Annotation with run-time retention should be copied by javac to bridge methods.
        ACTUAL -
        Bridge method has no annotations.

        ---------- BEGIN SOURCE ----------
        public interface Transform<A,B> {
          B transform(A a);
        }
        public class DigitCount<Integer,Integer> {
          public Integer transform(@Nullable Integer i) {
            return i == null ? 0 : i.toString().length();
          }
        }
        public class TestMe {
          public static void main(String[] args) {
            boolean hasAnnotation = false;
            try {
               Class c = Class.forName(args[0]);
               if (!Transform.class.isAssignableFrom(c)) return;
               Method m = c.getMethod("transform", Object.class);
               Annotation[] anot = m.getParameterAnnotations()[0];
               for (Annotation a: anot) {
                 if (a.annotationType().equals(Nullable.class)) hasAnnotation = true;
               }
            } catch (Exception e) {
              e.printStackTrace();
            }
            System.out.println(hasAnnotation);
          }
        }

        //run TestMe DigitCount
        ---------- END SOURCE ----------

        CUSTOMER SUBMITTED WORKAROUND :
        It is possible sometimes to retrieve the right class for the parameter using the technique described by Neal Gafter here: http://gafter.blogspot.com/2006/12/super-type-tokens.html. Only instead of getGenericSuperclass(), getGenericInterfaces() can be used, and the one which corresponds to Transform will be interrogated for its types.

        However it won't work for following example:

        public class AsString<T> implements Transform<T,String> {
            public String transform(T t) {
              return t.toString();
            }
         }
        public class IntegerAsString extends AsString<Integer> {
            public String transform(@Nullable Integer i) {
              return i == null ? null : i.toString();
            }
        }

        It will work if IntegerAsString is defined to explicitly implement Transform<Integer,String>.

        Attachments

          Issue Links

            Activity

              People

                vromero Vicente Arturo Romero Zaldivar
                ndcosta Nelson Dcosta (Inactive)
                Votes:
                0 Vote for this issue
                Watchers:
                4 Start watching this issue

                Dates

                  Created:
                  Updated:
                  Resolved:
                  Imported:
                  Indexed: