Hi,

On Tue, Nov 24, 2020 at 7:35 PM Alan Bateman <alan.bate...@oracle.com> wrote:
> On 24/11/2020 18:21, Simone Bordet wrote:
> > Hi,
> >
> > testing the Jetty MethodHandle usages we encountered this situation:
> >
> > .class org.openjdk.mh.Main
> > ----
> > Class<?> klass = Main.class;
> > MethodHandles.Lookup lookup = MethodHandles.publicLookup().in(klass);
> > MethodHandle handle = lookup.findVirtual(klass, "test",
> > MethodType.methodType(String.class));
> > ----
> >
> > .module-info.java
> > ----
> > module org.openjdk.mh {
> >      exports org.openjdk.mh to com.acme;
> > }
> > ----
> >
> > findVirtual() throws:
> > java.lang.IllegalAccessException: symbolic reference class is not
> > accessible: class org.openjdk.mh.Main, from
> > org.openjdk.mh.Main/noaccess (module org.openjdk.mh)
> >
> > Removing the "to" clause from the exports in module-info.java fixes the 
> > issue.
> >
> > Seems that a class cannot get a MethodHandle on itself, the reason
> > being that org.openjdk.mh is selectively exported in module-info.java.
> >
> > Is this intended behavior?
> > I would have expected that a class could always get a MethodHandle on 
> > itself.
> > I tested this with 11, 15, and 16+25, all fail.
> >
> > I have a simple reproducer, and I can open an OpenJDK bug.
> >
> It looks like you are starting with publicLookup and then teleporting to
> mh.Main that is not accessible to that lookup. When you change it from a
> qualified export  to exporting it to all modules then it becomes
> accessible to the lookup so that is why it works.

The "publicLookup()" should give (minimal) access to public classes
and public methods.

We want this minimal access requirement because Jetty creates a
MethodHandle on classes that are typically written by users.
We don't want Jetty to require that users classes are "opened" (in
JPMS meaning) because we only need to access public classes and public
methods.

The problem stems while trying to run our own test cases that happen
to be in the same module (test classes are patched to main classes of
the module).
In this case, the "user class" is a test class in the same package and
module as the main classes which, differently from real "user
classes", have a more restricted JPMS exports clause.

It broke my least surprise principle that a class cannot get a
MethodHandle on one of its own public methods using publicLookup() --
I assumed a class is implicitly exported to its own module, so why
would it not work?

> Have you tried starting with MethodHandles.lookup() ?

I do and it solves the issue at hand, but it's not the right way to
obtain the Lookup in our case because it requires more access than
needed to user classes (they must open themselves to Jetty
implementation modules).

I'd like to gently push on "why cannot a publicLookup().in(klass) work
on a public method of klass itself?".

Seems straightforward that it should, independently of exports
declarations, because it's a class "reflecting" on itself.

Thanks for bearing with my gentle push :)

-- 
Simone Bordet
---
Finally, no matter how good the architecture and design are,
to deliver bug-free software with optimal performance and reliability,
the implementation technique must be flawless.   Victoria Livschitz

Reply via email to