Re: MethodHandles.Lookup and modules

2015-12-18 Thread John Rose

> On Dec 18, 2015, at 4:44 PM, Alex Buckley  wrote:
...
> So let's recap full power lookups:
> 
> - 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 L's lookup class cannot access A (for example, A is 
> package-private in a different package than L's lookup class), then the 
> resulting lookup object has lookup mode NOACCESS. Otherwise:
> 
>  -- If A is in a different module than L's lookup class, then the resulting 
> lookup object has lookup mode NOACCESS.
> 
>  -- If A is in the same module as L's lookup class, but a different package, 
> then the resulting lookup object has lookup modes no greater than PUBLIC + 
> QUALIFIED + MODULE.
> 
>  -- 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 no greater than PUBLIC + QUALIFIED + MODULE + PACKAGE.
> 
>  -- If A is nested in the same package member as L's lookup class, then the 
> resulting lookup object has lookup modes no greater than PUBLIC + QUALIFIED + 
> MODULE + PACKAGE + PRIVATE.
> 
>  -- If A is the same class as L's lookup class, then the resulting lookup 
> object has the same lookup modes as L.

I agree; that's just how they teleport.

> 
>> 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.
> 
> Since PUBLIC is just UNCONDITIONAL with a concern for readability, it's 
> surprising that publicLookup cares about PUBLIC.

The PUBLIC bit is along for the ride.  It's meaningless when accompanied by 
UNCONDITIONAL, and can stay on, meaningfully, after UNCONDITIONAL drops off.

(Actually, PUBLIC is also required when you are looking up a *member* C.M of 
class C using publicLookup.  Both C and C.M had better be marked "public".  And 
you had better have the PUBLIC mode bit set so you can make use of that fact.  
The C.M is not marked "unconditional".)

> Before saying any more about that, let me take a small detour. I seem to 
> recall an intent to specify the public lookup object as representing an 
> (undisclosed) lookup class in the unnamed module ... if so, then since the 
> unnamed module reads all named modules by decree, we have 
> UNCONDITIONAL+PUBLIC as trivially equal in access power to PUBLIC, and we 
> don't need UNCONDITIONAL at all ... if not, then publicLookup could be 
> UNCONDITIONAL only.

True; this uses that odd feature of the unnamed module.  It's clever, but 
surprising.

With UNCONDITIONAL, though, we don't need to use that feature, and can 
compatibly retain the JDK7/8 behavior of PL.LC == Object.

Also, without UNCONDITIONAL, you can't teleport publicLookup to another module 
(you drop to NOACCESS).

That is a mildly bad thing, because Lookup.findClass assumes flexible 
teleportation.

The use case with PL is:
Q: I want to find an unconditionally readable class named "Foo", from the 
viewpoint (classloader & module) of the class Bar whose Class object Bar.class 
I possess.  How?
A: publicLookup().in(Bar.class).findClass("Foo").

Basically, adding UNCONDITIONAL allows Lookup to manage the magic directly, 
instead of leaning on the unnamed module, with more power to boot.

UNCONDITIONAL also tracks the fact that the Lookup object came from 
publicLookup, not full-power-lookup.  If not a mode bit, how else will be do it?

> Returning from the detour ... does the public lookup object have PUBLIC 
> solely so that it can teleport to give new lookup objects which drop 
> UNCONDITIONAL but still retain the interesting PUBLIC mode?

Yes; see above for an example.

> Proceeding to walk through a publicLookup:
> 
> - Start with an arbitrary class in an arbitrary module calling 
> MethodHandles.Lookup.publicLookup() to get a public lookup object PL. PL's 
> lookup mode is UNCONDITIONAL [+ PUBLIC?].

Yes, UNCONDITIONAL + PUBLIC.

> - The arbitrary class obtains a Class object representing class A, then calls 
> PL.in(A). If PL's lookup class cannot access A [I'm not sure what PL's lookup 
> class is, but it seems plausible that it can't access A], then the resulting 
> lookup object has lookup mode NOACCESS.

If PACKAGE(A) is unconditionally exported by its module, then all is well, 
since the UNCONDITIONAL bit enables the required read.

> Otherwise:
> 
>  -- If A is in a different module than PL's lookup class, then the resulting 
> lookup object has lookup mode UNCONDITIONAL. ???

Still UNCONDITIONAL + PUBLIC.  When the teleported lookup is used, it also 
ignores read edges.

> -- If A is in the same module

Re: MethodHandles.Lookup and modules

2015-12-18 Thread Alex Buckley

On 12/18/2015 12:20 AM, John Rose wrote:

On Dec 17, 2015, at 6:01 PM, John Rose mailto: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
distinctionbetween 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.


So let's recap full power lookups:

- 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 L's lookup class cannot access A (for example, A is 
package-private in a different package than L's lookup class), then the 
resulting lookup object has lookup mode NOACCESS. Otherwise:


  -- If A is in a different module than L's lookup class, then the 
resulting lookup object has lookup mode NOACCESS.


  -- If A is in the same module as L's lookup class, but a different 
package, then the resulting lookup object has lookup modes no greater 
than PUBLIC + QUALIFIED + MODULE.


  -- 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 no greater than PUBLIC + 
QUALIFIED + MODULE + PACKAGE.


  -- If A is nested in the same package member as L's lookup class, 
then the resulting lookup object has lookup modes no greater than PUBLIC 
+ QUALIFIED + MODULE + PACKAGE + PRIVATE.


  -- If A is the same class as L's lookup class, then the resulting 
lookup object has the same lookup modes as L.



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.


Since PUBLIC is just UNCONDITIONAL with a concern for readability, it's 
surprising that publicLookup cares about PUBLIC.


Before saying any more about that, let me take a small detour. I seem to 
recall an intent to specify the public lookup object as representing an 
(undisclosed) lookup class in the unnamed module ... if so, then since 
the unnamed module reads all named modules by decree, we have 
UNCONDITIONAL+PUBLIC as trivially equal in access power to PUBLIC, and 
we don't need UNCONDITIONAL at all ... if not, then publicLookup could 
be UNCONDITIONAL only.


Returning from the detour ... does the public lookup object have PUBLIC 
solely so that it can teleport to give new lookup objects which drop 
UNCONDITIONAL but still retain the interesting PUBLIC mode?


Proceeding to walk through a publicLookup:

- Start with an arbitrary class in an arbitrary module calling 
MethodHandles.Lookup.publicLookup() to get a public lookup object PL. 
PL's lookup mode is UNCONDITIONAL [+ PUBLIC?].


- The arbitrary class obtains a Class object representing class A, then 
calls PL.in(A). If PL's lookup class cannot access A [I'm not sure what 
PL's lookup class is, but it seems plausible that it can't access A], 
then the resulting lookup object has lookup mode NOACCESS

hg: jigsaw/jake/jaxws: 8144342: javac doesn't report errors if module exports non-existent package

2015-12-18 Thread jonathan . gibbons
Changeset: ab43de1d28fd
Author:vromero
Date:  2015-12-17 14:38 -0800
URL:   http://hg.openjdk.java.net/jigsaw/jake/jaxws/rev/ab43de1d28fd

8144342: javac doesn't report errors if module exports non-existent package

! src/jdk.xml.bind/share/classes/module-info.java



hg: jigsaw/jake/langtools: 8145016: Javac doesn't report errors on service implementation which cannot be initialized

2015-12-18 Thread jonathan . gibbons
Changeset: 4a70ae037273
Author:vromero
Date:  2015-12-17 13:41 -0800
URL:   http://hg.openjdk.java.net/jigsaw/jake/langtools/rev/4a70ae037273

8145016: Javac doesn't report errors on service implementation which cannot be 
initialized

! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java
! 
src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
+ test/tools/javac/modules/AbstractOrInnerClassServiceImplTest.java



hg: jigsaw/jake/langtools: 8145012: Javac doesn't report errors on duplicate uses or provides

2015-12-18 Thread jonathan . gibbons
Changeset: f22706341c4d
Author:vromero
Date:  2015-12-16 17:29 -0800
URL:   http://hg.openjdk.java.net/jigsaw/jake/langtools/rev/f22706341c4d

8145012: Javac doesn't report errors on duplicate uses or provides

! src/jdk.compiler/share/classes/com/sun/tools/javac/code/Directive.java
! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java
! 
src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
+ test/tools/javac/modules/RepeatedUsesAndProvidesTest.java



Re: Spring's need for optional dependencies

2015-12-18 Thread Paul Benedict
That doesn't bode well for frameworks that must run in JDK 8 and 9 --
either in classpath mode or module mode. That means the addReads() call
will have to be reflective so it can work in both worlds. That's just
another hack.

Cheers,
Paul

On Fri, Dec 18, 2015 at 11:33 AM, Neil Bartlett 
wrote:

> I do not see any statement in the Module System Requirements document (
> http://openjdk.java.net/projects/jigsaw/spec/reqs/) such that Java 9 is
> required to be backwards compatible, except where code runs in “classpath
> mode” (aka the unnamed module).
>
> Therefore it is an acceptable solution — at least if you accept the
> Requirements! — to need explicit API calls such as addReads() in frameworks
> when running in module mode.
>
> Regards,
> Neil
>
> > On 18 Dec 2015, at 16:14, Paul Benedict  wrote:
> >
> > Adding read edges at runtime is not a backward compatible solution.
> Jigsaw
> > should automatically allow you to read anything your Module Descriptor
> > gives you access to -- required or optional.
> >
> > Cheers,
> > Paul
> >
> > On Fri, Dec 18, 2015 at 10:02 AM, Peter Levart 
> > wrote:
> >
> >>
> >>
> >> On 12/18/2015 04:49 PM, Peter Levart wrote:
> >>
> >>> You can check whether the optional module is included in a runtime
> >>> configuration or not with a simple Class.forName() check even if you
> don't
> >>> depend on the module (i.e. don't list it in "requires" descriptor at
> >>> runtime). The visibility of classes is not restricted. It only depends
> on
> >>> ClassLoader hierarchy. When you successfully resolve some optional
> class at
> >>> runtime (with Class.forName), you then have to add a read edge to it's
> >>> module:
> >>>
> >>>Class optionalClass = Class.forName("...");
> >>>MySelfClass.getModule().addRead(optionalClass.getModule());
> >>>
> >>> ...before invoking any code that uses this module.
> >>>
> >>
> >> Just had an idea!
> >>
> >> Optional dependency at runtime could add a read edge to the module if
> that
> >> module was included in the configuration, but would otherwise not cause
> >> that module to be included in the configuration by itself. How does that
> >> sound? Spring would work as before - no .addRead() calls needed. Just
> >> Class.forName("OptionalClass").
> >>
> >> Regards, Peter
> >>
>
>


Re: Spring's need for optional dependencies

2015-12-18 Thread Neil Bartlett
I do not see any statement in the Module System Requirements document 
(http://openjdk.java.net/projects/jigsaw/spec/reqs/) such that Java 9 is 
required to be backwards compatible, except where code runs in “classpath mode” 
(aka the unnamed module).

Therefore it is an acceptable solution — at least if you accept the 
Requirements! — to need explicit API calls such as addReads() in frameworks 
when running in module mode.

Regards,
Neil

> On 18 Dec 2015, at 16:14, Paul Benedict  wrote:
> 
> Adding read edges at runtime is not a backward compatible solution. Jigsaw
> should automatically allow you to read anything your Module Descriptor
> gives you access to -- required or optional.
> 
> Cheers,
> Paul
> 
> On Fri, Dec 18, 2015 at 10:02 AM, Peter Levart 
> wrote:
> 
>> 
>> 
>> On 12/18/2015 04:49 PM, Peter Levart wrote:
>> 
>>> You can check whether the optional module is included in a runtime
>>> configuration or not with a simple Class.forName() check even if you don't
>>> depend on the module (i.e. don't list it in "requires" descriptor at
>>> runtime). The visibility of classes is not restricted. It only depends on
>>> ClassLoader hierarchy. When you successfully resolve some optional class at
>>> runtime (with Class.forName), you then have to add a read edge to it's
>>> module:
>>> 
>>>Class optionalClass = Class.forName("...");
>>>MySelfClass.getModule().addRead(optionalClass.getModule());
>>> 
>>> ...before invoking any code that uses this module.
>>> 
>> 
>> Just had an idea!
>> 
>> Optional dependency at runtime could add a read edge to the module if that
>> module was included in the configuration, but would otherwise not cause
>> that module to be included in the configuration by itself. How does that
>> sound? Spring would work as before - no .addRead() calls needed. Just
>> Class.forName("OptionalClass").
>> 
>> Regards, Peter
>> 



Re: Spring's need for optional dependencies

2015-12-18 Thread Peter Levart



On 12/18/2015 05:28 PM, Ali Ebrahimi wrote:

Hi,
Can we all agree that native Optional dependency support would be 
clean, best and reasonable solution.


I think we 3 do agree ;-).

Regards, Peter



On Fri, Dec 18, 2015 at 7:47 PM, Peter Levart > wrote:


Hi Ali,

On 12/18/2015 05:05 PM, Ali Ebrahimi wrote:

Hi,
In general, your workaround has some disadvantages:
1) Existing code does not work as is: (your need read edges)


See my message written concurrently with your's ;-) Optional
dependency could add a read edge for you if the target module was
pulled in by some other means, but would not cause it to be pulled in.


2) command line options only apply to boot layer not to dynamic
configurations created by future containers


Who knows what future containers will do. They are free to add all
modules deployed in a deployment unit as root modules to the layer
configuration. Root modules could be listed in a deployment
descriptor of the deployment unit. Jigsaw is providing the API for
them to do what they want.

Regards, Peter




On Fri, Dec 18, 2015 at 7:19 PM, Peter Levart
mailto:peter.lev...@gmail.com>> wrote:

Hi Paul,

I think we are not in disagreement. We are just talking of
slightly different things. So let me answer your concerns...

On 12/17/2015 06:14 PM, Paul Benedict wrote:

Peter, thanks for your comments. I differ in that I don't
see any problems with optional dependencies. Right now,
like in Spring, optional features are enabled with a
Class.forName() runtime check; if ClassNotFoundException
is captured, the feature is unavailable. I expect that
coding pattern to continue with optional dependencies.
Libraries know how to check if a class is available and
fallback to another plan when it's not.


You can check whether the optional module is included in a
runtime configuration or not with a simple Class.forName()
check even if you don't depend on the module (i.e. don't list
it in "requires" descriptor at runtime). The visibility of
classes is not restricted. It only depends on ClassLoader
hierarchy. When you successfully resolve some optional class
at runtime (with Class.forName), you then have to add a read
edge to it's module:

Class optionalClass = Class.forName("...");
MySelfClass.getModule().addRead(optionalClass.getModule());

...before invoking any code that uses this module.

What's different with jigsaw is how you include an optional
module in the runtime configuration.

Now you do this:

java -classpath :/path/to/my-optional-module.jar:...

With jigsaw you do this:

java -mp /repository/of/modules -addmods
...:my-optional-module:...

What's nice is that you don't have to remember to put the
module into the 'repository-of-modules'. You just have to
remember to '-addmods my-optional-module' and jigsaw will
tell you if it can't find it. So you have explicit control
from command line.


Regarding your concern on the command line, I am not sure
if people will be using the command line often. I expect
tools to eventually read the Module Descriptors and
assemble the correct list of modules. I believe Maven is
currently investigating something similar right now.
Currently, Jigsaw only reads a module directory, but
eventually individual jars will be able to be listed.
Just let tools solve this problem.


I think this feature is only meant to simplify establishing a
set of searchable modules when each of them is found in a
directory with some other files that would otherwise be in
the way if the directory as a whole was included in the
modulepath (think of automatic modules). And that's only
needed when compiling or running directly from the layout of
Maven local repository. Application assembly usually puts all
modules into a single archive. I believe this could be a
.jimage file in the future.

When you put something in -modulepath, it does not
automatically become part of your runtime configuration and I
think it should not. The concept of listing the root
module(s) explicitly and letting the system figure out the
transitive closure which then becomes a set of modules
included in the runtime configuration is a powerful concept.
And I think optional modules should not automatically be
included in the runtime configuration.

All that Juergen has to tell jigsaw Spring users is to
"require" the modules that are Spring opt

Re: Spring's need for optional dependencies

2015-12-18 Thread Paul Benedict
Peter, when you say Jigsaw  "doesn't search for module B" when it's
optional, what do you mean by "search"?

Cheers,
Paul

On Fri, Dec 18, 2015 at 10:42 AM, Peter Levart 
wrote:

> Hi Paul,
>
> On 12/18/2015 05:14 PM, Paul Benedict wrote:
>
> Adding read edges at runtime is not a backward compatible solution. Jigsaw
> should automatically allow you to read anything your Module Descriptor
> gives you access to -- required or optional.
>
>
> I was maybe not clear enough. So here's in the example. Suppose module A
> is a root module (the one mentioned in java -m option):
>
> module A {
> requires B;
> }
>
> ...searches for module B on -module-path and adds it to runtime
> configuration, failing to start the program if B is not found. If B is
> found it adds a read edge from A -> B.
>
> module A {
> requires optional B;
> }
>
> ... doesn't search for module B but still adds a read edge from A -> B if
> B happens to be included in the configuration by some other means. The
> 'other means' could be anything from:
>
> - some other module that is already a part of configuration "requires B"
> (say a root application module directly or a transitive dependency)
> - adding -addmods B command line option
> - deployment descriptor of a .mwar application says so
>
>
> I can certainly say that this is backward compatible in code. The code
> stays the same.
>
> I'm all *for* intorducing optional dependencies concept into the
> deployment descriptor. It's just that I don't see -modulepath as an
> equivalent to -classpath in the sense that optional dependency should make
> module part of the configuration when it happens to be searchable.
>
> Regards, Peter
>
>
> Cheers,
> Paul
>
> On Fri, Dec 18, 2015 at 10:02 AM, Peter Levart 
> wrote:
>
>>
>>
>> On 12/18/2015 04:49 PM, Peter Levart wrote:
>>
>>> You can check whether the optional module is included in a runtime
>>> configuration or not with a simple Class.forName() check even if you don't
>>> depend on the module (i.e. don't list it in "requires" descriptor at
>>> runtime). The visibility of classes is not restricted. It only depends on
>>> ClassLoader hierarchy. When you successfully resolve some optional class at
>>> runtime (with Class.forName), you then have to add a read edge to it's
>>> module:
>>>
>>> Class optionalClass = Class.forName("...");
>>> MySelfClass.getModule().addRead(optionalClass.getModule());
>>>
>>> ...before invoking any code that uses this module.
>>>
>>
>> Just had an idea!
>>
>> Optional dependency at runtime could add a read edge to the module if
>> that module was included in the configuration, but would otherwise not
>> cause that module to be included in the configuration by itself. How does
>> that sound? Spring would work as before - no .addRead() calls needed. Just
>> Class.forName("OptionalClass").
>>
>> Regards, Peter
>>
>
>
>


Re: Spring's need for optional dependencies

2015-12-18 Thread Peter Levart

Hi Paul,

On 12/18/2015 05:14 PM, Paul Benedict wrote:
Adding read edges at runtime is not a backward compatible solution. 
Jigsaw should automatically allow you to read anything your Module 
Descriptor gives you access to -- required or optional.


I was maybe not clear enough. So here's in the example. Suppose module A 
is a root module (the one mentioned in java -m option):


module A {
requires B;
}

...searches for module B on -module-path and adds it to runtime 
configuration, failing to start the program if B is not found. If B is 
found it adds a read edge from A -> B.


module A {
requires optional B;
}

... doesn't search for module B but still adds a read edge from A -> B 
if B happens to be included in the configuration by some other means. 
The 'other means' could be anything from:


- some other module that is already a part of configuration "requires B" 
(say a root application module directly or a transitive dependency)

- adding -addmods B command line option
- deployment descriptor of a .mwar application says so


I can certainly say that this is backward compatible in code. The code 
stays the same.


I'm all *for* intorducing optional dependencies concept into the 
deployment descriptor. It's just that I don't see -modulepath as an 
equivalent to -classpath in the sense that optional dependency should 
make module part of the configuration when it happens to be searchable.


Regards, Peter



Cheers,
Paul

On Fri, Dec 18, 2015 at 10:02 AM, Peter Levart > wrote:




On 12/18/2015 04:49 PM, Peter Levart wrote:

You can check whether the optional module is included in a
runtime configuration or not with a simple Class.forName()
check even if you don't depend on the module (i.e. don't list
it in "requires" descriptor at runtime). The visibility of
classes is not restricted. It only depends on ClassLoader
hierarchy. When you successfully resolve some optional class
at runtime (with Class.forName), you then have to add a read
edge to it's module:

Class optionalClass = Class.forName("...");
MySelfClass.getModule().addRead(optionalClass.getModule());

...before invoking any code that uses this module.


Just had an idea!

Optional dependency at runtime could add a read edge to the module
if that module was included in the configuration, but would
otherwise not cause that module to be included in the
configuration by itself. How does that sound? Spring would work as
before - no .addRead() calls needed. Just
Class.forName("OptionalClass").

Regards, Peter






Re: Spring's need for optional dependencies

2015-12-18 Thread Ali Ebrahimi
Hi,
Can we all agree that native Optional dependency support would be clean,
best and reasonable solution.

On Fri, Dec 18, 2015 at 7:47 PM, Peter Levart 
wrote:

> Hi Ali,
>
> On 12/18/2015 05:05 PM, Ali Ebrahimi wrote:
>
> Hi,
> In general, your workaround has some disadvantages:
> 1) Existing code does not work as is: (your need read edges)
>
>
> See my message written concurrently with your's ;-) Optional dependency
> could add a read edge for you if the target module was pulled in by some
> other means, but would not cause it to be pulled in.
>
> 2) command line options only apply to boot layer not to dynamic
> configurations created by future containers
>
>
> Who knows what future containers will do. They are free to add all modules
> deployed in a deployment unit as root modules to the layer configuration.
> Root modules could be listed in a deployment descriptor of the deployment
> unit. Jigsaw is providing the API for them to do what they want.
>
> Regards, Peter
>
>
>
> On Fri, Dec 18, 2015 at 7:19 PM, Peter Levart 
> wrote:
>
>> Hi Paul,
>>
>> I think we are not in disagreement. We are just talking of slightly
>> different things. So let me answer your concerns...
>>
>> On 12/17/2015 06:14 PM, Paul Benedict wrote:
>>
>>> Peter, thanks for your comments. I differ in that I don't see any
>>> problems with optional dependencies. Right now, like in Spring, optional
>>> features are enabled with a Class.forName() runtime check; if
>>> ClassNotFoundException is captured, the feature is unavailable. I expect
>>> that coding pattern to continue with optional dependencies. Libraries know
>>> how to check if a class is available and fallback to another plan when it's
>>> not.
>>>
>>
>> You can check whether the optional module is included in a runtime
>> configuration or not with a simple Class.forName() check even if you don't
>> depend on the module (i.e. don't list it in "requires" descriptor at
>> runtime). The visibility of classes is not restricted. It only depends on
>> ClassLoader hierarchy. When you successfully resolve some optional class at
>> runtime (with Class.forName), you then have to add a read edge to it's
>> module:
>>
>> Class optionalClass = Class.forName("...");
>> MySelfClass.getModule().addRead(optionalClass.getModule());
>>
>> ...before invoking any code that uses this module.
>>
>> What's different with jigsaw is how you include an optional module in the
>> runtime configuration.
>>
>> Now you do this:
>>
>> java -classpath :/path/to/my-optional-module.jar:...
>>
>> With jigsaw you do this:
>>
>> java -mp /repository/of/modules -addmods ...:my-optional-module:...
>>
>> What's nice is that you don't have to remember to put the module into the
>> 'repository-of-modules'. You just have to remember to '-addmods
>> my-optional-module' and jigsaw will tell you if it can't find it. So you
>> have explicit control from command line.
>>
>>
>>> Regarding your concern on the command line, I am not sure if people will
>>> be using the command line often. I expect tools to eventually read the
>>> Module Descriptors and assemble the correct list of modules. I believe
>>> Maven is currently investigating something similar right now. Currently,
>>> Jigsaw only reads a module directory, but eventually individual jars will
>>> be able to be listed. Just let tools solve this problem.
>>>
>>
>> I think this feature is only meant to simplify establishing a set of
>> searchable modules when each of them is found in a directory with some
>> other files that would otherwise be in the way if the directory as a whole
>> was included in the modulepath (think of automatic modules). And that's
>> only needed when compiling or running directly from the layout of Maven
>> local repository. Application assembly usually puts all modules into a
>> single archive. I believe this could be a .jimage file in the future.
>>
>> When you put something in -modulepath, it does not automatically become
>> part of your runtime configuration and I think it should not. The concept
>> of listing the root module(s) explicitly and letting the system figure out
>> the transitive closure which then becomes a set of modules included in the
>> runtime configuration is a powerful concept. And I think optional modules
>> should not automatically be included in the runtime configuration.
>>
>> All that Juergen has to tell jigsaw Spring users is to "require" the
>> modules that are Spring optional dependencies in their own root application
>> module and jigsaw will make sure they are included at runtime. Or users can
>> choose to delay that decision to launch runtime by not "require"-ing the
>> modules and using -addmods option instead.
>>
>> Regards, Peter
>>
>>
>>> Cheers,
>>> Paul
>>>
>>> On Thu, Dec 17, 2015 at 10:58 AM, Peter Levart <
>>> peter.lev...@gmail.com >> peter.lev...@gmail.com>> wrote:
>>>
>>> Hi,
>>>
>>>
>>> On 12/17/2015 12:03 PM, Stephen Colebourne wrote:
>>>
>>> And here are the thr

Re: Spring's need for optional dependencies

2015-12-18 Thread Peter Levart

Hi Ali,

On 12/18/2015 05:05 PM, Ali Ebrahimi wrote:

Hi,
In general, your workaround has some disadvantages:
1) Existing code does not work as is: (your need read edges)


See my message written concurrently with your's ;-) Optional dependency 
could add a read edge for you if the target module was pulled in by some 
other means, but would not cause it to be pulled in.


2) command line options only apply to boot layer not to dynamic 
configurations created by future containers


Who knows what future containers will do. They are free to add all 
modules deployed in a deployment unit as root modules to the layer 
configuration. Root modules could be listed in a deployment descriptor 
of the deployment unit. Jigsaw is providing the API for them to do what 
they want.


Regards, Peter



On Fri, Dec 18, 2015 at 7:19 PM, Peter Levart > wrote:


Hi Paul,

I think we are not in disagreement. We are just talking of
slightly different things. So let me answer your concerns...

On 12/17/2015 06:14 PM, Paul Benedict wrote:

Peter, thanks for your comments. I differ in that I don't see
any problems with optional dependencies. Right now, like in
Spring, optional features are enabled with a Class.forName()
runtime check; if ClassNotFoundException is captured, the
feature is unavailable. I expect that coding pattern to
continue with optional dependencies. Libraries know how to
check if a class is available and fallback to another plan
when it's not.


You can check whether the optional module is included in a runtime
configuration or not with a simple Class.forName() check even if
you don't depend on the module (i.e. don't list it in "requires"
descriptor at runtime). The visibility of classes is not
restricted. It only depends on ClassLoader hierarchy. When you
successfully resolve some optional class at runtime (with
Class.forName), you then have to add a read edge to it's module:

Class optionalClass = Class.forName("...");
MySelfClass.getModule().addRead(optionalClass.getModule());

...before invoking any code that uses this module.

What's different with jigsaw is how you include an optional module
in the runtime configuration.

Now you do this:

java -classpath :/path/to/my-optional-module.jar:...

With jigsaw you do this:

java -mp /repository/of/modules -addmods
...:my-optional-module:...

What's nice is that you don't have to remember to put the module
into the 'repository-of-modules'. You just have to remember to
'-addmods my-optional-module' and jigsaw will tell you if it can't
find it. So you have explicit control from command line.


Regarding your concern on the command line, I am not sure if
people will be using the command line often. I expect tools to
eventually read the Module Descriptors and assemble the
correct list of modules. I believe Maven is currently
investigating something similar right now. Currently, Jigsaw
only reads a module directory, but eventually individual jars
will be able to be listed. Just let tools solve this problem.


I think this feature is only meant to simplify establishing a set
of searchable modules when each of them is found in a directory
with some other files that would otherwise be in the way if the
directory as a whole was included in the modulepath (think of
automatic modules). And that's only needed when compiling or
running directly from the layout of Maven local repository.
Application assembly usually puts all modules into a single
archive. I believe this could be a .jimage file in the future.

When you put something in -modulepath, it does not automatically
become part of your runtime configuration and I think it should
not. The concept of listing the root module(s) explicitly and
letting the system figure out the transitive closure which then
becomes a set of modules included in the runtime configuration is
a powerful concept. And I think optional modules should not
automatically be included in the runtime configuration.

All that Juergen has to tell jigsaw Spring users is to "require"
the modules that are Spring optional dependencies in their own
root application module and jigsaw will make sure they are
included at runtime. Or users can choose to delay that decision to
launch runtime by not "require"-ing the modules and using -addmods
option instead.

Regards, Peter


Cheers,
Paul

On Thu, Dec 17, 2015 at 10:58 AM, Peter Levart
mailto:peter.lev...@gmail.com>
>> wrote:

Hi,


On 12/17/2015 12:03 PM, Stephen Colebourne wrote:

And here are the threads for Joda pro

Re: Spring's need for optional dependencies

2015-12-18 Thread Paul Benedict
Adding read edges at runtime is not a backward compatible solution. Jigsaw
should automatically allow you to read anything your Module Descriptor
gives you access to -- required or optional.

Cheers,
Paul

On Fri, Dec 18, 2015 at 10:02 AM, Peter Levart 
wrote:

>
>
> On 12/18/2015 04:49 PM, Peter Levart wrote:
>
>> You can check whether the optional module is included in a runtime
>> configuration or not with a simple Class.forName() check even if you don't
>> depend on the module (i.e. don't list it in "requires" descriptor at
>> runtime). The visibility of classes is not restricted. It only depends on
>> ClassLoader hierarchy. When you successfully resolve some optional class at
>> runtime (with Class.forName), you then have to add a read edge to it's
>> module:
>>
>> Class optionalClass = Class.forName("...");
>> MySelfClass.getModule().addRead(optionalClass.getModule());
>>
>> ...before invoking any code that uses this module.
>>
>
> Just had an idea!
>
> Optional dependency at runtime could add a read edge to the module if that
> module was included in the configuration, but would otherwise not cause
> that module to be included in the configuration by itself. How does that
> sound? Spring would work as before - no .addRead() calls needed. Just
> Class.forName("OptionalClass").
>
> Regards, Peter
>


Re: Spring's need for optional dependencies

2015-12-18 Thread Ali Ebrahimi
Hi,
In general, your workaround has some disadvantages:
1) Existing code does not work as is: (your need read edges)
2) command line options only apply to boot layer not to dynamic
configurations created by future containers

On Fri, Dec 18, 2015 at 7:19 PM, Peter Levart 
wrote:

> Hi Paul,
>
> I think we are not in disagreement. We are just talking of slightly
> different things. So let me answer your concerns...
>
> On 12/17/2015 06:14 PM, Paul Benedict wrote:
>
>> Peter, thanks for your comments. I differ in that I don't see any
>> problems with optional dependencies. Right now, like in Spring, optional
>> features are enabled with a Class.forName() runtime check; if
>> ClassNotFoundException is captured, the feature is unavailable. I expect
>> that coding pattern to continue with optional dependencies. Libraries know
>> how to check if a class is available and fallback to another plan when it's
>> not.
>>
>
> You can check whether the optional module is included in a runtime
> configuration or not with a simple Class.forName() check even if you don't
> depend on the module (i.e. don't list it in "requires" descriptor at
> runtime). The visibility of classes is not restricted. It only depends on
> ClassLoader hierarchy. When you successfully resolve some optional class at
> runtime (with Class.forName), you then have to add a read edge to it's
> module:
>
> Class optionalClass = Class.forName("...");
> MySelfClass.getModule().addRead(optionalClass.getModule());
>
> ...before invoking any code that uses this module.
>
> What's different with jigsaw is how you include an optional module in the
> runtime configuration.
>
> Now you do this:
>
> java -classpath :/path/to/my-optional-module.jar:...
>
> With jigsaw you do this:
>
> java -mp /repository/of/modules -addmods ...:my-optional-module:...
>
> What's nice is that you don't have to remember to put the module into the
> 'repository-of-modules'. You just have to remember to '-addmods
> my-optional-module' and jigsaw will tell you if it can't find it. So you
> have explicit control from command line.
>
>
>> Regarding your concern on the command line, I am not sure if people will
>> be using the command line often. I expect tools to eventually read the
>> Module Descriptors and assemble the correct list of modules. I believe
>> Maven is currently investigating something similar right now. Currently,
>> Jigsaw only reads a module directory, but eventually individual jars will
>> be able to be listed. Just let tools solve this problem.
>>
>
> I think this feature is only meant to simplify establishing a set of
> searchable modules when each of them is found in a directory with some
> other files that would otherwise be in the way if the directory as a whole
> was included in the modulepath (think of automatic modules). And that's
> only needed when compiling or running directly from the layout of Maven
> local repository. Application assembly usually puts all modules into a
> single archive. I believe this could be a .jimage file in the future.
>
> When you put something in -modulepath, it does not automatically become
> part of your runtime configuration and I think it should not. The concept
> of listing the root module(s) explicitly and letting the system figure out
> the transitive closure which then becomes a set of modules included in the
> runtime configuration is a powerful concept. And I think optional modules
> should not automatically be included in the runtime configuration.
>
> All that Juergen has to tell jigsaw Spring users is to "require" the
> modules that are Spring optional dependencies in their own root application
> module and jigsaw will make sure they are included at runtime. Or users can
> choose to delay that decision to launch runtime by not "require"-ing the
> modules and using -addmods option instead.
>
> Regards, Peter
>
>
>> Cheers,
>> Paul
>>
>> On Thu, Dec 17, 2015 at 10:58 AM, Peter Levart > > wrote:
>>
>> Hi,
>>
>>
>> On 12/17/2015 12:03 PM, Stephen Colebourne wrote:
>>
>> And here are the threads for Joda projects, which also need
>> optional
>> dependencies:
>>
>> http://mail.openjdk.java.net/pipermail/jigsaw-dev/2015-December/005462.html
>>
>> http://mail.openjdk.java.net/pipermail/jigsaw-dev/2015-December/005638.html
>>
>> Note, I do not consider command line flags to be acceptable as
>> a solution.
>>
>> Stephen
>>
>>
>> On 17 December 2015 at 09:41, Stephane Epardaud
>> mailto:s...@epardaud.fr>> wrote:
>>
>> As I already mentioned, we also have the need for this in
>> Ceylon, for
>> the same reasons. Dependencies are required at
>> compile-time but optional
>> at run-time, based on detection: if it's there fine, if
>> not then no problem.
>>
>>
>>
>> The only problem I see with optional dependencies at runtime is as
>> 

Re: Spring's need for optional dependencies

2015-12-18 Thread Peter Levart



On 12/18/2015 04:49 PM, Peter Levart wrote:
You can check whether the optional module is included in a runtime 
configuration or not with a simple Class.forName() check even if you 
don't depend on the module (i.e. don't list it in "requires" 
descriptor at runtime). The visibility of classes is not restricted. 
It only depends on ClassLoader hierarchy. When you successfully 
resolve some optional class at runtime (with Class.forName), you then 
have to add a read edge to it's module:


Class optionalClass = Class.forName("...");
MySelfClass.getModule().addRead(optionalClass.getModule());

...before invoking any code that uses this module.


Just had an idea!

Optional dependency at runtime could add a read edge to the module if 
that module was included in the configuration, but would otherwise not 
cause that module to be included in the configuration by itself. How 
does that sound? Spring would work as before - no .addRead() calls 
needed. Just Class.forName("OptionalClass").


Regards, Peter


Re: Spring's need for optional dependencies

2015-12-18 Thread Peter Levart

Hi Paul,

I think we are not in disagreement. We are just talking of slightly 
different things. So let me answer your concerns...


On 12/17/2015 06:14 PM, Paul Benedict wrote:
Peter, thanks for your comments. I differ in that I don't see any 
problems with optional dependencies. Right now, like in Spring, 
optional features are enabled with a Class.forName() runtime check; if 
ClassNotFoundException is captured, the feature is unavailable. I 
expect that coding pattern to continue with optional dependencies. 
Libraries know how to check if a class is available and fallback to 
another plan when it's not.


You can check whether the optional module is included in a runtime 
configuration or not with a simple Class.forName() check even if you 
don't depend on the module (i.e. don't list it in "requires" descriptor 
at runtime). The visibility of classes is not restricted. It only 
depends on ClassLoader hierarchy. When you successfully resolve some 
optional class at runtime (with Class.forName), you then have to add a 
read edge to it's module:


Class optionalClass = Class.forName("...");
MySelfClass.getModule().addRead(optionalClass.getModule());

...before invoking any code that uses this module.

What's different with jigsaw is how you include an optional module in 
the runtime configuration.


Now you do this:

java -classpath :/path/to/my-optional-module.jar:...

With jigsaw you do this:

java -mp /repository/of/modules -addmods ...:my-optional-module:...

What's nice is that you don't have to remember to put the module into 
the 'repository-of-modules'. You just have to remember to '-addmods 
my-optional-module' and jigsaw will tell you if it can't find it. So you 
have explicit control from command line.




Regarding your concern on the command line, I am not sure if people 
will be using the command line often. I expect tools to eventually 
read the Module Descriptors and assemble the correct list of modules. 
I believe Maven is currently investigating something similar right 
now. Currently, Jigsaw only reads a module directory, but eventually 
individual jars will be able to be listed. Just let tools solve this 
problem.


I think this feature is only meant to simplify establishing a set of 
searchable modules when each of them is found in a directory with some 
other files that would otherwise be in the way if the directory as a 
whole was included in the modulepath (think of automatic modules). And 
that's only needed when compiling or running directly from the layout of 
Maven local repository. Application assembly usually puts all modules 
into a single archive. I believe this could be a .jimage file in the future.


When you put something in -modulepath, it does not automatically become 
part of your runtime configuration and I think it should not. The 
concept of listing the root module(s) explicitly and letting the system 
figure out the transitive closure which then becomes a set of modules 
included in the runtime configuration is a powerful concept. And I think 
optional modules should not automatically be included in the runtime 
configuration.


All that Juergen has to tell jigsaw Spring users is to "require" the 
modules that are Spring optional dependencies in their own root 
application module and jigsaw will make sure they are included at 
runtime. Or users can choose to delay that decision to launch runtime by 
not "require"-ing the modules and using -addmods option instead.


Regards, Peter



Cheers,
Paul

On Thu, Dec 17, 2015 at 10:58 AM, Peter Levart > wrote:


Hi,


On 12/17/2015 12:03 PM, Stephen Colebourne wrote:

And here are the threads for Joda projects, which also need
optional
dependencies:

http://mail.openjdk.java.net/pipermail/jigsaw-dev/2015-December/005462.html

http://mail.openjdk.java.net/pipermail/jigsaw-dev/2015-December/005638.html

Note, I do not consider command line flags to be acceptable as
a solution.

Stephen


On 17 December 2015 at 09:41, Stephane Epardaud
mailto:s...@epardaud.fr>> wrote:

As I already mentioned, we also have the need for this in
Ceylon, for
the same reasons. Dependencies are required at
compile-time but optional
at run-time, based on detection: if it's there fine, if
not then no problem.



The only problem I see with optional dependencies at runtime is as
follows...

If "requires optional X" semantic was to include the module X in
configuration if it could be found with module finder (on
-modulepath), otherwise not, then the established configuration
would not only be dependent on command-line arguments, but also on
the content of module directories. If there was a common directory
used as a repository for various modules, you would not be able to
opt-out of using a particular module i

hg: jigsaw/jake/jdk: 4 new changesets

2015-12-18 Thread alan . bateman
Changeset: 387f9070f3bf
Author:alanb
Date:  2015-12-18 12:11 +
URL:   http://hg.openjdk.java.net/jigsaw/jake/jdk/rev/387f9070f3bf

Layer.createWithXXX need additional permisions specified
Misc. clean-up

! src/java.base/share/classes/java/lang/reflect/Layer.java
! src/java.base/share/classes/jdk/internal/misc/Loader.java

Changeset: bfe6c859bc80
Author:alanb
Date:  2015-12-18 12:21 +
URL:   http://hg.openjdk.java.net/jigsaw/jake/jdk/rev/bfe6c859bc80

Fix comment on Module.module

! src/java.base/share/classes/java/lang/Class.java
! src/java.base/share/classes/jdk/internal/misc/BootLoader.java

Changeset: 4ec6952f50e1
Author:alanb
Date:  2015-12-18 14:48 +
URL:   http://hg.openjdk.java.net/jigsaw/jake/jdk/rev/4ec6952f50e1

Expand test coverage for Layer.createWithXXX

! test/jdk/jigsaw/reflect/Layer/LayerAndLoadersTest.java
! test/jdk/jigsaw/reflect/Layer/src/m1/module-info.java
! test/jdk/jigsaw/reflect/Layer/src/m1/p/Main.java
- test/jdk/jigsaw/reflect/Layer/src/m3/impl/ServiceImpl.java
! test/jdk/jigsaw/reflect/Layer/src/m3/module-info.java
+ test/jdk/jigsaw/reflect/Layer/src/m3/w/Hello.java
+ test/jdk/jigsaw/reflect/Layer/src/m4/impl/ServiceImpl.java
+ test/jdk/jigsaw/reflect/Layer/src/m4/module-info.java

Changeset: 85367e9f7812
Author:alanb
Date:  2015-12-18 14:51 +
URL:   http://hg.openjdk.java.net/jigsaw/jake/jdk/rev/85367e9f7812

jdk.rmi.rmic should be exported by jdk.rmic module

! src/jdk.rmic/share/classes/module-info.java



Re: MethodHandles.Lookup and modules

2015-12-18 Thread John Rose
On Dec 17, 2015, at 6:01 PM, John Rose  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.

When looking up a type member T.M, the additional access checking on the
member's enclosing type T (from LC) may lack PACKAGE, MODULE, QUALIFIED,
and PUBLIC modes (if excludeModes stripped those bits from a full-power lookup).
This means that such mode-stripped lookups can (logically) only obtain members
LC.M from the single lookup class LC (since a class always has access to 
itself).
That seems reasonable and useful.

A stripped lookup with only MODULE or QUALIFIED bits will never be able to "see"
any T.M, since members only match in PUBLIC, PRIVATE, PROTECTED, and
PACKAGE modes.  Odd, and probably not useful, but logical.

There does not seem to be a way to say "give me only the T.M for which T
is package-private and M is public", or "give me only the T.M for which T
is module-private but M is public".  Those can be composed on top,
especially with the new Lookup.accessClass API point as a post-test on T.

As an odd use case, a stripped lookup with only PACKAGE modes
will be able to see any package-mate T of LC, and any package-private
API point T.M, but it won't be able to query anything *outside* of the
package of T.  Unfortunately, it also won't be able to query any public
member T.M, unless the PUBLIC bit is present.  So I suppose stripping
MODULE and QUALIFIED, leaving PUBLIC and PACKAGE, would
provide useful access to T.M even if M were public.

As you see, I'm trying to apply the same mode bits to both types
and their members, as mechanically as possible.  One place where
that is tricky is with UNCONDITIONAL.  That is rescued by making
sure that UNCONDITIONAL will not lose PUBLIC even if teleported.

About monotonicity:

The rul