On 09/12/2015 14:54, stanislav lukyanov wrote:
1) Lookup.in() javadoc says
"If the lookup for this Lookup is in a named module, and the new
lookup class is in a different
module M, then no members, not even public members in M's exported
packages, will be accessible"
However, it seems to be possible to have PUBLIC access after
lookupInA.in(ClassInB.class)
without breaking "no more access capabilities than the original" rule.
Are such transitions intentionally forbidden?
Yes, this is intention as the lookup class and mode bits would otherwise
not be sufficient when you teleport through a sequence of lookup
classes. It might be clearer if you extend the example to
in(B.class).in(C.class).in(D.class) where B, C and D are in different
named modules and work out the intersection.
2) Lookup.in() javadoc says
"If the lookup class for this Lookup is not in a named module, and the
new lookup class is
in a named module M, then no members in M's non-exported packages will
be accessible"
Spec says nothing about M's 'requires' and 'exports to M'.
In current implementation, modules required by M are still accessible
and packages exported to M (with 'exports to') are not accessible.
It seems right that packages exported to M are not accessible.
Should it be specified in the javadoc, or is it implied due to
definitions somewhere else?
It is implied because the javadoc provides the guarantee that the
resulting Lookup has no more access than the original. In this case
there are packages exported by M's friends to M that are not accessible
to code in unnamed modules. However, I think you are right that this
could be make clearer in the javadoc. I'm sure that once the design
settles down that we'll do several passes over the javadoc.
:
However, this creates some uncertainty.
Suppose we have A requires B. From user's point resulting lookup of
publicLookup().in(ClassInA.class)
may or may not have access to the module B - it depends on module A's
'requires' which user doesn't know about.
It may come to the following situation. Code
publicLookup().in(BlassInA.class).findStatic(ClassInB.class, "m",
...).invoke()
works with version of A that have 'requires B'.
In the next version, A removes 'requires B' which should not
have any impact on A's users, but the code above stops working.
Sure, the other thing is that readability graph can mutate at run-time
so that `A` reads additional modules.
3) publicLookup() seems to allow work around the module access control.
publicLookup() is available for any module and has access to any
module's exported packages.
So, if we have modules A and B that do not require each other, we can
still access B from A:
// code in A
publicLookup().in(ClassInB.class)
Is it OK to be able to do such tricks?
The publicLookup can only be used to access types that are are public
and in packages that are exported unconditionally. It can't be used to
break encapsulation, either directly or by teleporting and using a
lookup class in another module.
Also `A` can call addReads to read any other module so this allows it to
access any public type in any package exported by other modules if it
really wants. This means that there is nothing that the publicLookup can
be used to access that `A` can't access anyway.
-Alan