Java Platform Module System
Alex Buckley
alex.buckley at oracle.com
Mon May 1 20:06:08 UTC 2017
On 4/30/2017 4:10 AM, Stephan Herrmann wrote:
> No. (B) may be true for your example, but it is not for the following
> (which is similar to examples we had in our January thread):
>
> //-- M/module-info.java
> module M { exports pm; }
>
> //-- M/impl/Other.java
> package impl;
> public class Other { }
>
> //-- M/pm/C1.java
> package pm;
> import impl.Other;
> public class C1 extends Other {
> public void m1(Other o) {}
> }
> //--
> //-- O/module-info.java
> module O { requires M; }
>
> //-- O/impl/Other.java
> package impl;
> public class Other { }
>
> //-- O/po/Client.java
> package po;
> import pm.C1;
> public class Client {
> void test1(C1 one) {
> one.m1(one);
> }
> }
> //--
>
> Looking at O, and trying to determine whether the method invocation
> one.m1(one)
> is legal, M's type impl.Other is *relevant*, because analysis must ...
> - detect that the type reference "Other" in the signature of m1 refers
> to the
> type defined in M, not to the same-named type in O.
> - similarly detect that the type reference in C1's class header (or
> superclass
> classfile attribute) refers to M's impl.Other.
> - conclude from the above, that C1 is compatible to m1's parameter.
>
> Ergo, the set of types relevant from the perspective of O contains two
> same-named types.
Per 7.3, it's true that when compiling any observable ordinary
compilation units associated with O (such as O/po/Client.java), the host
system must limit the ordinary compilation units that would otherwise be
observable, to only those that are visible to O. Since O requires M, and
since M/impl/Other.java is an observable ordinary compilation unit
associated with M, we have that M/impl/Other.java is visible to O.
Then, by 6.3, the scope of M's top-level impl package is all observable
compilation units in O.
Then, we get the difficulty in 6.5.3.2, because two top-level packages
called impl are visible to code in O.
I specified package visibility in 7.3 in the way I did -- not
considering exports -- in order to encourage compilers to take a "wide
view" of what packages are physically present in required modules, even
if a package isn't exported (M's package impl) and thus its types won't
be accessible (M's type impl.Other isn't accessible to code in O).
For example, if M's author forgets to export impl (quite possible when M
is first declared), I'd like a tool processing O to have the words to
say: "impl is /visible/ in M, but not exported, so none of its types --
not even its 'public' types -- can be accessed".
> If Java 9 permits this situation, it not only hugely increases the
> complexity
> of all tools that need to "understand" this program, it also wastes a
> unique
> opportunity that JPMS has, which existing module systems did not have:
>
> Java 9 could make "API leaks" either illegal or ineffective and thus
> rule out
> an entire category of ill-formed programs, which to-date must unfortunately
> be accepted by module-unaware compilers:
>
> (A) Java 9 has the opportunity to say that the declaration of m1 is
> illegal,
> because it publicly exposes a non-accessible type, which is broken in
> every regard.
>
> (B) Alternatively, Java 9 has the opportunity to say that any attempt to
> invoke m1 from outside M is illegal, because clients would need to know
> about an inaccessible type.
Understood, but we didn't take those directions. More here:
https://bugs.openjdk.java.net/browse/JDK-8153362
Alex
More information about the jigsaw-dev
mailing list