Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8040656

Classes with overriden methods with covariant returns return random read methods

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: P3
    • Resolution: Fixed
    • Affects Version/s: 7u21
    • Fix Version/s: 9
    • Component/s: client-libs
    • Labels:
    • Subcomponent:
    • Resolved In Build:
      b15
    • OS:
      linux

      Backports

        Description

        FULL PRODUCT VERSION :
        java version " 1.7.0_21 "
        Java(TM) SE Runtime Environment (build 1.7.0_21-b11)
        Java HotSpot(TM) 64-Bit Server VM (build 23.21-b01, mixed mode)


        ADDITIONAL OS VERSION INFORMATION :
        Linux 2.6.32-48-generic #110-Ubuntu SMP Fri May 31 18:32:53 UTC 2013 x86_64 GNU/Linux


        A DESCRIPTION OF THE PROBLEM :
        Consider a bean class B that implements an interface, and which has a bean method with a covariant return type:

        public interface A {
                public Object getFoo();
            }

        public class B implements A {
                @Override
                public String getFoo() {
                    return null;
                }
        }

        When you call Introspector.getBeanInfo(B.class).getMethodDescriptors(), the method descriptor for getFoo() randomly returns either Object getFoo() (a synthetic bridge method added by javac due to covariant return types) or String getFoo() (the actual method that appears in B).

        REGRESSION. Last worked in version 6u45

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        Execute the following program. I classes B and C are identical except for some dummy methods added to B. On my machine this prints:

        public java.lang.String scrap.IntrospectorTest$B.getFoo()
        public java.lang.Object scrap.IntrospectorTest$C.getFoo()

        I would expect it to return identically for both classes, since the getFoo() method is identical. If you add or remove additional dummy methods to the classes, the results change. If you kick off some threads or do other heavy things before doing the introspection, the result changes. Basically the return value is random (but the B vs C was the easiest way I found to make a reproducible test case).

        Because of the randomness, you might get different results on your machine!


        ACTUAL -
        See above.

        ERROR MESSAGES/STACK TRACES THAT OCCUR :
        See above

        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        package scrap;

        import java.beans.*;

        public class IntrospectorTest {
            
            public interface A {
                public Object getFoo();
            }
            
            public class B implements A {
                @Override
                public String getFoo() {
                    return null;
                }
                
                // if you add/delete these dummy methods, the bean method for getFoo() will
                // flip back and fort between Object getFoo() (bride) and String getFoo() (the
                // covariant method that actually appears in the source)
                public Object getFoo1() { return null; }
                public Object getFoo2() { return null; }
                public Object getFoo3() { return null; }
                public Object getFoo4() { return null; }
                public Object getFoo5() { return null; }
            }
            
            public class C implements A {
                @Override
                public String getFoo() {
                    return null;
                }
            }

            public static void main(String[] args) throws Exception {
                printMethods(B.class);
                printMethods(C.class);

            }

            private static void printMethods(final Class<?> clazz) throws IntrospectionException {
                BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
                for (MethodDescriptor desc : beanInfo.getMethodDescriptors()) {
                    if (desc.getName().equals( " getFoo " )) {
                        System.out.println(desc.getMethod());
                    }
                }
            }

        }
        ---------- END SOURCE ----------

          Attachments

            Issue Links

              Activity

                People

                Assignee:
                malenkov Sergey Malenkov (Inactive)
                Reporter:
                webbuggrp Webbug Group
                Votes:
                0 Vote for this issue
                Watchers:
                4 Start watching this issue

                  Dates

                  Created:
                  Updated:
                  Resolved: