FYI, we just had a useful conversation about how the new readability
restrictions from Jigsaw modules should affect the MHs.Lookup API.
Specifically, we need a couple more access modes to represent the new
layers of type readability (interacts with lookup and accessibility),
plus a special behavior (another access mode bit) for publicLookup,
to represent the fact that there is no longer a true global scope.
Given the increased complexity of access layers we also want to
add a (trivial) API point to directly drop access mode bits from a Lookup.
See http://mail.openjdk.java.net/pipermail/jigsaw-dev/2015-December/005829.html
(copied below) and nearby messages.
The Jigsaw guys have a charming name for what Lookup.in does:
It "teleports" a lookup to another location. Teleporting outside a module
tends to shut down all access rights (to preserve monotonicity of privilege),
except for publicLookup which retains its special globalized viewpoint.
This is a refinement on the current Lookup enhancement in the Jigsaw repo.
As one consequence, the publicLookup.lookupClass can go back to
being Object, and is usefully teleportable elsewhere, so that (in turn)
it is broadly useful with the new API point Lookup.findClass, which
uses the lookupClass as a starting point for name resolution.
— John
Begin forwarded message:
From: John Rose <john.r.r...@oracle.com>
Subject: Re: MethodHandles.Lookup and modules
Date: December 18, 2015 at 12:20:08 AM PST
To: Alex Buckley <alex.buck...@oracle.com>
Cc: jigsaw-...@openjdk.java.net
On Dec 17, 2015, at 6:01 PM, John Rose <john.r.r...@oracle.com> wrote:
>
> I think I would prefer case 2. The user model is PUBLIC is the weakest
> (non-empty) access
> mode available to bytecode behaviors. As such it respects the LC's position
> in the module
> graph, and excludes module-private, package-private, and class-private.
> UNCONDITIONAL
> is the special thing provided by publicLookup, which ignores the module
> graph. Then
> PACKAGE opens up the LC's package, MODULE opens up the LC's module, and
> PRIVATE
> opens up the LC itself (plus its nestmates). Feels pretty good, especially
> since MODULE
> and PACKAGE continue to have a parallel sense of restriction.
>
> What do you think?
So I caught you in the hall and we talked, and this seems agreeable to us both,
perhaps with a name change to UNCONDITIONAL, and also a distinction between
PUBLIC and QUALIFIED (as you originally proposed).
To try and tease out some symmetry here:
- Always, any type T is accessible to itself, when T = LC.
- PACKAGE mode: Any type T is accessible (within its own package), when
PACKAGE(T) = PACKAGE(LC).
- MODULE mode: A public type T is accessible (within or beyond its package),
when MODULE(T) = MODULE(LC).
- QUALIFIED mode: A public type T is accessible beyond its module, when
IS_CE(T, LC),
where IS_CE(T, LC) = IS_CONDITIONALLY_EXPORTED(PACKAGE(T), MODULE(LC)) and
MODULE(LC) READS MODULE(T).
- PUBLIC mode: A public type T is accessible beyond its module friends when
IS_UE(T, LC),
where IS_UE(T, LC) = IS_UNCONDITIONALLY_EXPORTED(PACKAGE(T)) and MODULE(LC)
READS MODULE(T).
These conditions can be tested independently. PACKAGE implies MODULE, but
everything else is disjoint.
Also:
- UNCONDITIONAL: In this mode, a type T is accessible if
IS_UNCONDITIONALLY_EXPORTED(PACKAGE(T)), regardless of LC.
- PRIVATE/PROTECTED: These protection modes apply only to non-types (JVM does
not enforce "private" on classes).
- NOACCESS: This is not a mode but the absence of any combination of modes; no
access is allowed.
The publicLookup should have UNCONDITIONAL and PUBLIC set.
An original full-power lookup does *not* have UNCONDITIONAL set, just PUBLIC.
The purpose of UNCONDITIONAL is to allow publicLookup to be unconcerned
(as documented) about its LC. We can restore LC to be java.lang.Object.
The distinction between QUALIFIED and PUBLIC is present simply because of
the logical fact (as you point out) that, if you teleport to a new module, you
must lose your qualified imports, but you shouldn't lose your unconditional
ones.
The distinction between PUBLIC and UNCONDITIONAL is present in order
to capture the differing behaviors of lookups derived from publicLookup and
those derived from full-power lookups.
The presence of MODULE captures the larger but package-like scope of
a module's internal names.
About "mode stripping":
You suggested (which sounds OK) that there is no need to "validate" bit masks
of lookup objects.
Just have excludeModes clear some bits and continue. This means there can be
lookups which
are able to read (say) using PACKAGE mode but not PUBLIC mode. (Today's
lookups can
have PUBLIC without PACKAGE but not vice versa.) Each mode bit enables a single
line in the above logic, and (as you can see) the lines can be applied
independently.
Some implications follow.