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

[nestmates] IllegalAccessError using a protected method reference declared in super class in different package




      In the valhalla nestmates branch, lambda metafactory is updated and replace the use of
      `Unsafe::defineAnonymousClass` with `Lookup::defineHiddenClass`.
      The lambda proxy class is a hidden nestmate of the target class and it follows the proper access control checks.

      In javac, LambdaToMethod::isProtectedInSuperClassOfEnclosingClassInOtherPackage determines
      when to desugar a protected method reference to a static method. In the following example,
      p.T.Sub and p.T.Sub1 are a subclass of q.I whereas p.T is not a subclass of q.I.

      In Sub::test, super::readFile will get desugared to a static method in p.T.Sub to invoke q.I::readFile.
      However, this::readFile does not get desugared and such a protected method reference passed to
      p.T::m, p.T has no access to q.I::readFile. When the lambda proxy class of p.T is defined as a hidden
      nestmate class, IAE is thrown as it fails to access q.I::readFile.

      In Sub1::test, such a protected method reference passed to Sub1::test, Sub1 has access to q.I::readFile but the lambda proxy class does not since it's not a subclass of q.I. In this case, it should be desugared as well.

      ------------------- p/T.java
      package p;
      import q.I;
      import java.nio.file.Path;
      import java.nio.file.Paths;
      import java.util.function.Function;

      public class T {
          public static void main(String... args) throws Throwable {
              Path p = Paths.get("test");
              Sub sub = new Sub();
              Sub1 sub1 = new Sub1();

          private static void m(Function<Path,String> fileReader, Path path) {

          public static class Sub extends I {
              public void test(Path outputDir) {
                  // this method reference is desugared to a static method:
                  // REF_invokeSpecial p/T$Sub.lambda$test$0:(Ljava/nio/file/Path;)Ljava/lang/String;
                  // as Sub is in package p, a different package from its its superclass
                  m(super::readFile, outputDir);

                  // this compiles to indy LMF with:
                  // REF_invokeVirtual q/I.readFile:(Ljava/nio/file/Path;)Ljava/lang/String;
                  // p.T is not a subclass of q.I and so it has no access to q.I::readFile
                  m(this::readFile, outputDir);

          public static class Sub1 extends I {
              public void test(Path outputDir) {
                  test(this::readFile, outputDir);
              private void test(Function<Path,String> fileReader, Path path) {

      ----- q/I.java

      package q;
      import java.nio.file.Path;
      public class I {
          protected String readFile(Path file) {
              return file.toString();


      Attached test.zip reproduces the error when running with the binary built from valhalla nestmates branch.
      $ javac p/*.java q/*.java
      $ java p.Main

      Exception in thread "main" java.lang.IllegalAccessError: class p.Main$$Lambda$1$$/0x0000000800b76a70 tried to access protected method 'java.lang.String q.I.readFile(java.nio.file.Path)' (p.Main$$Lambda$1$$/0x0000000800b76a70 and q.I are in unnamed module of loader 'app')
      at q.J.checkFile(J.java:14)
      at q.J.check(J.java:18)
      at p.Main.test(Main.java:31)
      at p.Main.main(Main.java:13)

      test/langtools/jdk/javadoc/doclet/testSingletonLists/TestSingletonLists.java also fails because of this issue.


          Issue Links



              sadayapalam Srikanth Adayapalam
              mchung Mandy Chung
              0 Vote for this issue
              2 Start watching this issue