United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6888164 Bridge methods break obtaining of declaring class annotations
JDK-6888164 : Bridge methods break obtaining of declaring class annotations

Details
Type:
Bug
Submit Date:
2009-10-05
Status:
Resolved
Updated Date:
2013-04-09
Project Name:
JDK
Resolved Date:
2013-04-09
Component:
tools
OS:
linux
Sub-Component:
javac
CPU:
x86
Priority:
P3
Resolution:
Won't Fix
Affected Versions:
6u10
Fixed Versions:

Related Reports
Relates:

Sub Tasks

Description
FULL PRODUCT VERSION :
java version "1.6.0_10"
Java(TM) SE Runtime Environment (build 1.6.0_10-b33)
Java HotSpot(TM) 64-Bit Server VM (build 11.0-b15, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Linux sickboy-pc 2.6.27-11-generic #1 SMP Wed Apr 1 20:53:41 UTC 2009 x86_64 GNU/Linux

A DESCRIPTION OF THE PROBLEM :
java.beans.Introspector returns bridge methods (introduced in 6342411) as read/write methods. method.getDeclaringClass() in such case does not return the expected class (ancestor) where the methods are declared. User can't obtain annotations declared on the class where the property accessors were really declared.

This works with JDK5 compiled classes.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile classes with JDK6. Execute BeanInfoTest. It won't find any annotations on read/write methods of a property because it will return bridging methods and the declaring class of these bridging methods.

Compiled with JDK5 it finds annotations ok as the declaring class is the real class declaring the methods.

This was probably introduced by fix for issue 6342411.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Same as with JDK5 compiled classes. Because of this annotation based code might stop working.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
=================BeanInfoTest.java=================
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.*;

public class BeanInfoTest {

    public static void main(String[] args) throws IntrospectionException {
        final BeanInfo bi = Introspector.getBeanInfo(Descendant.class);
        final PropertyDescriptor[] pds = bi.getPropertyDescriptors();
        for (PropertyDescriptor p : pds) {
            System.out.println(p.getName() + ":");
            if (p.getReadMethod() != null) {
                info(p.getReadMethod());
            }
            if (p.getWriteMethod() != null) {
                info(p.getWriteMethod());
            }
        }
    }
    
    public static void info(Method m) {
        System.out.println(m.getDeclaringClass().getName() + "." + m.getName());
        System.out.println(Arrays.toString(m.getAnnotations()));
        System.out.println(Arrays.toString(m.getDeclaringClass().getAnnotations()));
    }
}

=================Ancestor.java=================
@Test
class Ancestor {

    private String a;

    @Test
    public String getA() {
        return a;
    }
    
    @Test
    public void setA(String a) {
        this.a = a;
    }
}
=================Descendant.java=================
public class Descendant extends Ancestor {

}
=================Test.java=================
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface Test {

}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Check whether the read/write method is synthetic bridge and try to find the same method in superclass(es).

                                    

Comments
This bug is more a reflection libraries issue than a javac issue.
                                     
2013-04-09



Hardware and Software, Engineered to Work Together