Details
-
Enhancement
-
Resolution: Fixed
-
P5
-
6
-
b94
-
x86
-
windows_xp
-
Verified
Backports
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8072365 | 7u85 | Unassigned | P5 | Resolved | Fixed | b01 |
JDK-8067255 | 7u80 | Vicente Arturo Romero Zaldivar | P5 | Resolved | Fixed | b04 |
Description
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
- backported by
-
JDK-8067255 Copy method annotations and parameter annotations to synthetic bridge methods
- Resolved
-
JDK-8072365 Copy method annotations and parameter annotations to synthetic bridge methods
- Resolved
- duplicates
-
JDK-8200205 Method.getAnnotations fails to find annotations under certain circumstances
- Closed
- relates to
-
JDK-8011026 javac, com.sun.source.util.Trees fail to retrieve class trees at GENERATE event
- Open
-
JDK-8010737 javac, known parameter's names should be copied to automatically generated constructors for inner classes
- Closed
-
JDK-8274617 annotations in the super class constructor are not propagated to the anonymous class constructor
- Resolved
-
JDK-8223116 Class#getDeclaredMethods and AccessibleObject#isAnnotationPresent print wrong values
- Resolved
-
JDK-6996415 Override bridges causes compiler-generated code to end up with synthetic infinite loop
- Closed
-
JDK-8015780 java/lang/reflect/Method/GenericStringTest.java failing
- Closed
-
JDK-8029563 Method.getAnnotations() changed its return value in JDK 8.
- Closed
-
JDK-8042785 javac, bridge methods are not getting the flags from the original method
- Closed
-
JDK-8078571 java.lang.reflect.method.isAnnotationPresent backward compatible at jdk-7u80
- Closed
-
JDK-8080370 Method annotation added in abstract super method
- Closed