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

Missing accessor for constructor reference pointing to private inner class ctor

    XMLWordPrintable

Details

    • Bug
    • Resolution: Fixed
    • P4
    • 8
    • 8
    • tools
    • OpenJDK build of jdk/tl

    • b82
    • Verified

    Description

      The following test code creates an instance of Enclosing, which then captures a constructor reference for a nested private class. The constructor reference wraps a newInvokeSpecial MH on the private ctor, which is accessbile to Enclosing. But, when we try and invoke it, we get an ICCE with a sub-error about accessibility.

      Test code:

          public void testPrivateInnerCtorRef() {
              Supplier<Object> ctor = new Enclosing().foo();
              System.out.println(ctor);
              System.out.println(ctor.get());
          }

          static class Enclosing {

              public Supplier<Object> foo() {
                  return Inner::new;
              }

              private class Inner {
                  private Inner() {}
              }
          }

      Error:

      java.lang.IncompatibleClassChangeError
              at java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:383)
              at org.openjdk.tests.java.lang.invoke.GenBadMHTest$Enclosing.foo(GenBadMHTest.java:106)
              at org.openjdk.tests.java.lang.invoke.GenBadMHTest.testPrivateInnerCtorRef(GenBadMHTest.java:98)
              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:474)
              at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:80)
              at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
              at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
              at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
              at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
              at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
              at org.testng.TestRunner.privateRun(TestRunner.java:767)
              at org.testng.TestRunner.run(TestRunner.java:617)
              at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
              at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
              at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
              at org.testng.SuiteRunner.run(SuiteRunner.java:240)
              at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
              at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
              at org.testng.TestNG.runSuitesSequentially(TestNG.java:1198)
              at org.testng.TestNG.runSuitesLocally(TestNG.java:1123)
              at org.testng.TestNG.run(TestNG.java:1031)
              at org.testng.TestNG.privateMain(TestNG.java:1338)
              at org.testng.TestNG.main(TestNG.java:1307)
      Caused by: java.lang.IllegalAccessException: member is private: org.openjdk.tests.java.lang.invoke.GenBadMHTest$Enclosing$Inner.<init>(Enclosing)void/invokeSpecial, from org.openjdk.tests.java.lang.invoke.GenBadMHTest$Enclosing
              at java.lang.invoke.MemberName.makeAccessException(MemberName.java:732)
              at java.lang.invoke.MethodHandles$Lookup.checkAccess(MethodHandles.java:1135)
              at java.lang.invoke.MethodHandles$Lookup.getDirectConstructor(MethodHandles.java:1243)
              at java.lang.invoke.MethodHandles$Lookup.linkMethodHandleConstant(MethodHandles.java:1270)
              at java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:381)

      Enclosing.foo() bytecode:

      public java.util.function.Supplier<java.lang.Object> foo();
          flags: ACC_PUBLIC
          Code:
            stack=1, locals=1, args_size=1
               0: aload_0
               1: invokedynamic #2, 0 // InvokeDynamic #0:lambda:(Lorg/openjdk/tests/java/lang/invoke/GenBadMHTest$Enclosing;)Ljava/util/function/Supplier;
               6: areturn

      BootstrapMethods:
          0: #24 invokestatic java/lang/invoke/LambdaMetafactory.metaFactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
            Method arguments:
              #25 invokeinterface java/util/function/Supplier.get:()Ljava/lang/Object;
              #26 newinvokespecial org/openjdk/tests/java/lang/invoke/GenBadMHTest$Enclosing$Inner."<init>":(Lorg/openjdk/tests/java/lang/invoke/GenBadMHTest$Enclosing;)V
              #27 ()Ljava/lang/Object;


      Issues:
      #1. Because the Inner ctor is accessible to Enclosing, the MH construction should be allowed, and then aren't we past the access check?

      #2. If the problem is indeed accessibility, why is ICCE thrown?

      Attachments

        Issue Links

          Activity

            People

              mcimadamore Maurizio Cimadamore
              mcimadamore Maurizio Cimadamore
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: