MethodHandles.lookup errors where publicLookup is ok

Charles Oliver Nutter headius at headius.com
Thu Sep 4 16:41:57 UTC 2025


On Wed, Sep 3, 2025 at 4:09 AM Alan Bateman <alan.bateman at oracle.com> wrote:

> Method handles are aligned with bytecode behavior, this includes access
> checks in the MH factory methods. If you were to inject code into module
> org.jruby.dist with a reference to a class in module X then any attempt in
> org.jruby.dist to access a class in module X would fail with
> IllegalAccessError. org.jruby.dist's module does not declare "requires X"
> and so org.jruby.dist does not read X.
>
> Lookup.publicLookup is the minimally trusted lookup to create method
> handles to public fields and methods. This necessitated the addition of the
> UNCONDITIONAL access mode even though it doesn't correspond to a modifier
> in the access flags. It means that the access check done with the
> publicLookup is closer to what you see with core reflection (where
> readability is assumed) rather than bytecode. This may seem complicated but
> it's not something that most developers will ever need to deal with
> directly.
>

Ok, I understand. Play with sharp tools, get cut. And given the evolution
of MH and Lookup over the years I'm not surprised my original expectations
from a decade ago don't quite match the modern reality of JPMS.


> Raising an error saying it "is not accessible" is also rather misleading
> when it actually **is** accessible
>
> It's not accessible from code in module org.jruby.dist so not accessible
> with the Lookup obtained from lookup(). That said, we need to improve the
> IAE exception messages. A lot of effort went into exception messages thrown
> by setAccessible/Method.invoke/Field.xxx where as the IAE exception
> messages thrown by the MH factory methods are less helpful.
>

I guess it will just take me some time to internalize the reality of "can't
be read until read access is requested" for cases that "magically" work
through traditional reflection. This discussion helps.

BTW: Your first message has "symbolic reference class is not accessible:
> class jdk.proxy4.$Proxy49" which suggests that the JRuby code may be
> attempting the findVirtual for the method in the proxy implementation class
> rather than the method in the interface class. You might to check that.
>

Fair point. We have typically assumed that if Modifier.isPublic(klass) was
true, we are good to go ahead and bind that class and its methods in our
Java integration layer and indy call sites. I'm testing a patch that adds
JRUBY_MODULE.canRead(klass.getModule()) to that requirement and so far it
fixes the original issue and does not appear to regress any other features.
Instead of binding Function.apply as Proxy49.apply, we should only bind it
against the public interface.

- Charlie
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/core-libs-dev/attachments/20250904/f4125b94/attachment.htm>


More information about the core-libs-dev mailing list