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

Runtime accessibility checking: protected class, if extended, should be accessible from another package

    Details

    • Subcomponent:
    • Introduced In Build:
      b100
    • Introduced In Version:
      8
    • Resolved In Build:
      b53

      Backports

        Description

        JSR 335 spec, chapter "15.28.2 Run-time Evaluation of Method References" contains following assertion:

        If the method reference has the form ExpressionName :: NonWildTypeArgumentsopt Identifier or Primary :: NonWildTypeArgumentsopt Identifier, the body of the invocation method has the effect of invoking the compile-time declaration of the method reference, as described in 15.12.4.3, 15.12.4.4, 15.12.4.5.[jsr335-15.28.2-41]

        This assertions refers to chapter "15.12.4.3. Check Accessibility of Type and Method" which contains following assertions:

        Let C be the class containing the method invocation, and let T be the qualifying type of the method invocation (§13.1), and let m be the name of the method as determined at compile-time (§15.12.3).
        ...
        If T is in a different package than C, and T is protected, then T is accessible if and only if C is a subclass of T.
        ...

        According to these assertions MethodInvoker.invoke should succeed, provided, the class files resulted form following sources compilation are supplied at run-time:

        MethodInvoker.java:
        import anotherpkg.MethodSupplierOuter;
        import anotherpkg.MethodSupplierFactory;

        public class MethodInvoker extends MethodSupplierOuter.MethodSupplier {
            public static void invoke() throws Exception {
                MethodInvoker ms = (MethodInvoker)MethodSupplierFactory.create();
                MyFunctionalInterface fi = ms::m;
                fi.invokeMethodReference();
            }
        }

        MethodSupplierOuter.java:
        package anotherpkg;

        public class MethodSupplierOuter {
            protected static class MethodSupplier {
                public void m() {
                    System.out.println("bad");
                }
            }
        }

        MethodSupplierFactory.java:
        package anotherpkg;

        public class MethodSupplierFactory {
            public static Object create() throws Exception {
                return Class.forName("MethodInvoker").newInstance();
            }
        }


        but exception is thrown instead resulting in following output:


        Exception in thread "main" java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:491)
        at Test.main(Test.java:7)
        Caused by: java.lang.IncompatibleClassChangeError
        at java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:383)
        at MethodInvoker.invoke(MethodInvoker.java:7)
        ... 5 more
        Caused by: java.lang.IllegalAccessException: symbolic reference class is not public: class anotherpkg.MethodSupplierOuter$MethodSupplier, from MethodInvoker
        at java.lang.invoke.MemberName.makeAccessException(MemberName.java:744)
        at java.lang.invoke.MethodHandles$Lookup.checkSymbolicClass(MethodHandles.java:1026)
        at java.lang.invoke.MethodHandles$Lookup.resolveOrFail(MethodHandles.java:1017)
        at java.lang.invoke.MethodHandles$Lookup.linkMethodHandleConstant(MethodHandles.java:1284)
        at java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:381)
        ... 6 more

        This was reproduced on b100, platform: Windows7x64.

        The minimized test is attached.
        The steps to reproduce the error are below, they should be performed in exactly specified order:

        1) compile Test.java from archive;
        2) compile sources from "anotherpkg" package from archive;
        3) compile MethodInvoker.java from archive;
        4) compile bad/MethodSupplier.java from archive;
        5) run Test.main.

          Attachments

            Issue Links

              Activity

                People

                • Assignee:
                  drchase David Chase (Inactive)
                  Reporter:
                  grakov Georgiy Rakov (Inactive)
                • Votes:
                  0 Vote for this issue
                  Watchers:
                  7 Start watching this issue

                  Dates

                  • Created:
                    Updated:
                    Resolved: