JDK 8 reflection changes (compared to JDK 7)

Pavel Bucek pavel.bucek at oracle.com
Tue Jan 28 03:33:14 PST 2014


Thanks Paul, that's exactly what I was looking for :)

have a nice day,
Pavel

On 28/01/14 12:16, Paul Sandoz wrote:
> 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 
> <mailto: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