IllegalAccessError when method reference resolves to method returning inaccessible class

Tagir Valeev amaembo at gmail.com
Thu May 5 06:54:15 UTC 2022


Thank you, Alex.

I also think that accepting the program is correct. However, it looks
like the resulting bytecode is not accepted by JVM. Probably, emitting
a bridge method is necessary here (effectively compiling the method
reference just like lambda).

With best regards,
Tagir Valeev.

On Wed, May 4, 2022 at 6:30 PM Alex Buckley <alex.buckley at oracle.com> wrote:
>
> I believe this program is accepted by JLS 15.13, and that accepting the
> program is correct. It has always been possible in Java to invoke a
> method whose return type is inaccessible to the caller, provided that
> the caller doesn't use the method's result at the inaccessible type.
> Fundamentally the same rules apply to the indirect invocation denoted by
> a method reference expression. Foo::bar is typed w.r.t. [the function
> type of] Supplier<Object>, for which an access check _is_ performed;
> however, Foo::bar is not typed w.r.t. anything involving the
> inaccessible nested type Foo.Bar, so Foo::bar is as legal as its
> "equivalent" lambda expression ()->Foo.bar().
>
> Alex
>
> On 5/4/2022 7:40 AM, Tagir Valeev wrote:
> > Consider the following code:
> >
> > // foo/Foo.java
> > package foo;
> >
> > public class Foo {
> >      public static Bar bar() {
> >          return new Bar();
> >      }
> >
> >      static class Bar {}
> > }
> >
> > // bar/Baz.java
> > package bar;
> >
> > import foo.Foo;
> > import java.util.function.Supplier;
> >
> > public class Baz {
> >      public static  void foo(Supplier<Object> supplier) {
> >          System.out.println(supplier.get());
> >      }
> >
> >      public static void main(String[] args) {
> >          Baz.foo(Foo::bar);
> >      }
> > }
> >
> > It's perfectly compilable (tried javac 17 and 19-ea) but immediately
> > fails at runtime with
> >
> > Exception in thread "main" java.lang.IllegalAccessError: failed to
> > access class foo.Foo$Bar from class bar.Baz (foo.Foo$Bar and bar.Baz
> > are in unnamed module of loader 'app')
> > at bar.Baz.main(Baz.java:14)
> >
> > It looks like VM doesn't like if bootstrap method refers to a method
> > that mentions inaccessible type in a signature. However, we can
> > normally call the same method in lambda:
> >
> > public static void main(String[] args) {
> >      Baz.foo(() -> Foo.bar());
> > }
> >
> > I'm not sure whether this is a compiler or VM problem but to me, it
> > looks wrong when the program after successful complete recompilation
> > fails with IllegalAccessError. Please correct me if this compiler
> > behavior is specified.
> >
> > With best regards,
> > Tagir Valeev


More information about the compiler-dev mailing list