JDK-6695379 : Copy method annotations and parameter annotations to synthetic bridge methods
  • Type: Enhancement
  • Status: Closed
  • Resolution: Fixed
  • Component: tools
  • Sub-Component: javac
  • Priority: P5
  • Affected Version: 6
  • OS: windows_xp
  • CPU: x86
  • Submit Date: 2008-04-29
  • Updated Date: 2017-05-16
  • Resolved Date: 2013-06-01
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availabitlity Release.

To download the current JDK release, click here.
JDK 7 JDK 8
7u80Resolved 8 b94Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
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>.

Comments
Parameter and method annotations are copied to synthetic bridge methods. This fix implies that now for programs like: @Target(value = {ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @interface ParamAnnotation {} @Target(value = {ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface MethodAnnotation {} abstract class T<A,B> { B m(A a){return null;} } class CovariantReturnType extends T<Integer, Integer> { @MethodAnnotation Integer m(@ParamAnnotation Integer i) { return i; } public class VisibilityChange extends CovariantReturnType {} } Each generated bridge method will have all the annotations of the method it redirects to. Parameter annotations will also be copied. This change in the behavior may impact some annotations processor or in general any application that use the annotations.
2013-11-21

Respective test: tools/javac/6889255/T6889255.java tools/javac/MethodParameters/ClassFileVisitor.java tools/javac/MethodParameters/ReflectionVisitor.java tools/javac/MethodParameters/Tester.java tools/javac/T6695379/AnnotationsAreNotCopiedToBridgeMethodsTest.java
2013-06-19

This patch is waiting for bug JDK-8011026 to be solved. The feature is needed for testing.
2013-04-10

waiting for ccc approval
2013-04-09