JDK 8 reflection changes (compared to JDK 7)
Paul Sandoz
paul.sandoz at oracle.com
Tue Jan 28 03:16:39 PST 2014
Hi Pavel,
The second method is a bridge method (m.isBridge() == true).
You can use javap to see the byte code generated by the Java 8 compiler on the Test.B class:
public void method(java.lang.Object);
flags: ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: aload_1
2: checkcast #2 // class java/lang/String
5: invokevirtual #3 // Method method:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 67: 0
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 this LTest$B;
RuntimeVisibleAnnotations:
0: #22()
Consider this code:
B b = new B();
A a = b; // raw type for A
a.method("FOO"); // will invoke the bridge
a.method(new Integer(1)); // ClassCastException
It was a bug that was fixed in 8:
https://bugs.openjdk.java.net/browse/JDK-6695379
but has not been backported to a 7 update release, and i dunno if it will.
Often for EE/reflection-based frameworks it is sufficient to ignore and filter out the bridge methods when processing the classes to find invocation points of user classes to be invoked by the framework (IIRC that is what Jersey did).
Hth,
Paul.
On Jan 28, 2014, at 11:40 AM, Pavel Bucek <pavel.bucek at oracle.com> wrote:
> Hi all,
>
> I hope this is correct mailing list - if not, please feel free to point me to different one.
>
> Consider following code:
>
> @Retention(RetentionPolicy.RUNTIME)
> @Target(ElementType.METHOD)
> @interface C { }
>
> abstract class A<T> {
> public abstract void method(T arg);
> }
>
> class B extends A<String> {
> @Override
> @C
> public void method(String arg) { }
> }
>
> public static void main(String[] args) {
> for(Method m : B.class.getMethods()) {
> if(m.isAnnotationPresent(C.class)) {
> System.out.println(m);
> }
> }
> }
>
> When executed on JDK8 (1.8.0-ea-b124), it prints out two methods:
>
> public void org.glassfish.tyrus.test.standard_config.GenericClientEndpointTest$B.method(java.lang.String)
> public void org.glassfish.tyrus.test.standard_config.GenericClientEndpointTest$B.method(java.lang.Object)
>
> result on JDK7 (just one method):
>
> public void org.glassfish.tyrus.test.standard_config.GenericClientEndpointTest$B.method(java.lang.String)
>
> Why is the method with Object param added to result set? And why it does have @C annotation declared? If this is intentional, is there any way how I could reliably filter out method with Object as parameter to get same result as on JDK7?
>
> Thanks and regards,
> Pavel
>
More information about the jdk8-dev
mailing list