MethodHandles.Lookup and modules
Alex Buckley
alex.buckley at oracle.com
Thu Dec 17 20:44:03 UTC 2015
Hi John,
On 12/11/2015 12:38 PM, John Rose wrote:
> That's fine. There are two main use cases for Lookup.in,
> neither of which require the tracking of long chains of L.in(A/B/C…).
>
> A. Agent with full-power lookup wants to invoke another agent with the lookup,
> but wants to limit access, because he doesn't fully trust the other agent.
> He does a single L.in(A) to a remote-enough type A, creating a non-full-power lookup.
> (Note: Picking A is sometimes non-trivial. This might be an API flaw.)
>
> B. Agent with full-power lookup wants to get access to private nestmate in A.
> He does a single L.in(A) where LC and A are in the same package member.
> This works around differences between access checks at JVM and JLS levels,
> just as the package-private accessor methods from javac do. (Yuck!)
Focusing on case A, please consider the following design:
- PUBLIC lookup mode means:
Any 'public' type of any package exported unconditionally by the
package's module.
- QUALIFIED lookup mode means:
Any 'public' type of any package exported in qualified fashion by the
package's module to the lookup class's module.
- MODULE lookup mode means:
Any 'public' type of any package in the lookup class's module.
(Sidebar: QUALIFIED is split from MODULE primarily to be explicit about
access rights and secondarily to support more precise slicing of access
rights in a future MethodHandles.Lookup API. Example: give me a lookup
object to access the types in this module that offer a contract, i.e.
are declared 'public' without regard to exported-ness. Example: give me
a lookup object to access the types outside this module which are
exported to it by its friends.)
- Start with an arbitrary class in an arbitrary module calling
MethodHandles.Lookup.lookup() to get a "full power" lookup object L. L's
lookup modes are PUBLIC + QUALIFIED + MODULE + PROTECTED + PACKAGE +
PRIVATE.
- The arbitrary class obtains a Class object representing class A, then
calls L.in(A):
-- If A is in a different module than L's lookup class, then the
resulting lookup object has lookup mode PUBLIC.
-- If A is in the same module as L's lookup class, but a different
package, then the resulting lookup object has lookup mode PUBLIC +
QUALIFIED + MODULE + PROTECTED. (#include some stuff about actually
accessing protected members outside A's package.)
-- If A is in the same module as L's lookup class, and in the same
package, but A is a different class than L's lookup class, then the
resulting lookup object has lookup modes PUBLIC + QUALIFIED + MODULE +
PROTECTED + PACKAGE.
-- If A is the same class as L's lookup class, then the resulting
lookup object has lookup modes PUBLIC + MODULE + PROTECTED + PACKAGE +
PRIVATE.
- L.in(A) succeeds (returns a lookup object) regardless of whether its
caller is in a module that reads A's module. Only when find* is called
on a lookup object is there a check that the caller-of-find*'s module
reads the module containing the lookup class embodied by the lookup
object. It's easy for the caller-of-find* to pass the check by calling
addReads(...) just before calling find*.
(Sidebar: Separately, the module containing the lookup class embodied by
the lookup object had better have readability to other modules in order
for find* to look up [ctors, methods, and fields of] classes in those
other modules.)
> Should there be a way to build a lookup, for two modules M1/M2, which
> reads those names of M2 which M1 can read, except no internals
> of M1? I wonder if such a thing would be useful? Probably not.
>
> But it would be useful to have a lookup in a module M1 which can
> read the exports of *every* M2 that M1 can see, except no M1 internals.
> (This includes the unconditionally exported public names of M1.)
> This would be a Lookup with an LC in M1 and flags of PUBLIC only.
The difference between these two paragraphs is hard to discern. The
first paragraph seems to fix M1 and M2 while the second paragraph fixes
M1 and varies M2, but there's also a switch from "M1 can read" to "M1
can see". Modules read modules, classes see classes, types access types.
Can you restate?
Alex
More information about the jigsaw-dev
mailing list