JDK-8005183 : Missing accessor for constructor reference pointing to private inner class ctor
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 8
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2012-12-18
  • Updated: 2013-06-06
  • Resolved: 2013-02-21
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8
8 b82Fixed
Related Reports
Cloners :  
Duplicate :  
Relates :  
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?
Comments
We should bridge this kind of method references - so that we make sure that Lower will generate all the accessors we need.
18-12-2012