This should, however, be completely safe in the case when one of those modules 
is part of the JDK itself, isn’t it? It is not clear to me how you could ever 
get a circular dependency in that case.

In fact, this should be true of any library as well - the only scenario that I 
can think of where you could get this mess is if a developer compiles a bunch 
of classes, and then deliberately creates circularity between modules by 
putting some of those classes into a named module and some into the unnamed 
module, which seems incredibly unlikely.

If there an actual plausible scenario from which you are hoping to protect 
developers with this restriction?

- Russ

> On Mar 9, 2016, at 8:56 PM, Alex Buckley <alex.buck...@oracle.com> wrote:
> 
> Yes, a ClassCastException could only arise when (sticking with Paul's 
> scenario) the same class exists in both the named module and the unnamed 
> module.
> 
> It would be "safe" for the module system to allow a package that is split 
> perfectly between modules: no overlap of classes and no cyclic references 
> between members. This is checkable when a package is split between two named 
> modules that the resolver can observe in great detail. (You don't even need 
> to check no-cyclic-references, since it's dominated by the 
> no-cyclic-dependencies rule for the modules -- basically the split has to be 
> perfect for the package to work at all.)
> 
> But in the case of a package split between a named module and the unnamed 
> module, the check is basically impossible, since the resolver can't enumerate 
> the A.* types in the unnamed module without scanning the classpath, which 
> sounds bad.
> 
> tl;dr We don't want a lot of gymnastics in the module system to support a 
> known-bad idiom which most Java developers will never come across. ("most" 
> means "in the millions".)
> 
> Alex
> 
> On 3/9/2016 5:16 PM, Russell Gold wrote:
>> Doesn’t this kind of error only happen when a second module exports
>> the same _class_? What is the problem with another class being
>> defined in the same package, given that package B isn’t going to
>> access that new class at all?
>> 
>> - Russ
>> 
>>> On Mar 9, 2016, at 4:37 PM, Alex Buckley <alex.buck...@oracle.com>
>>> wrote:
>>> 
>>> Presumably you would count the equivalent scenario on JDK 8 -- my
>>> package A is in Alex.jar on the classpath and your package A is in
>>> Paul.jar on the classpath -- as a security issue too, because some
>>> of my classes may substitute for yours (or some of yours for mine,
>>> depending on how the classpath is constructed).
>>> 
>>> On JDK 9, we do the "substitution" cleanly. Package A is not split.
>>> That avoids one category of error (ClassCastException). What about
>>> poor package B that finds itself accessing a different package A
>>> than it was compiled with? Well, since package A is exported by a
>>> named module, it's reasonable to assume that the named module
>>> "owns" package A [*], and that the developer of package B
>>> co-bundled some version of package A without renaming it. Dangerous
>>> in JDK 8, dangerous in JDK 9. (We're trying to encapsulate the
>>> internals of a module, which is different from trying to isolate
>>> modules from each other.)
>>> 
>>> [*] Advanced scenario: the named module exporting A is actually an
>>> automatic module which happened to co-bundle package A. By placing
>>> this JAR on the modulepath to form an automatic module, it
>>> dominates the JAR left on the classpath which also co-bundled
>>> package A.
>>> 
>>> Alex
>>> 
>>> On 3/9/2016 1:17 PM, Paul Benedict wrote:
>>>> But isn't what your proposing a security issue? Let's say my
>>>> package A is in the unnamed module and your package A is in a
>>>> named module. You basically took over my code; your classes will
>>>> be substituted for mine.
>>>> 
>>>> Cheers, Paul
>>>> 
>>>> On Wed, Mar 9, 2016 at 2:38 PM, Alex Buckley
>>>> <alex.buck...@oracle.com <mailto:alex.buck...@oracle.com>>
>>>> wrote:
>>>> 
>>>> On 3/9/2016 10:36 AM, Paul Benedict wrote:
>>>> 
>>>> From the doc: "If a package is defined in both a named module and
>>>> the unnamed module then the package in the unnamed module is
>>>> ignored. This preserves reliable configuration even in the face
>>>> of the chaos of the class path, ensuring that every module still
>>>> reads at most one module defining a given package. If, in our
>>>> example above, a JAR file on the class path contains a class file
>>>> named com/foo/bar/alpha/AlphaFactory.class then that file will
>>>> never be loaded, since the com.foo.bar.alpha package is exported
>>>> by the com.foo.bar module."
>>>> 
>>>> I would like some clarification. Correct me if wrong, but I think
>>>> this entire paragraph is really meant to be about the perspective
>>>> from a modularized JAR? If a module has package A, and the
>>>> unnamed module has package A, then of course the module's package
>>>> A should win.
>>>> 
>>>> However, if it is meant to be absolute language, then I
>>>> disagree.
>>>> 
>>>> The unnamed module should be coherent among itself. If the
>>>> unnamed module has package B and relies on classes from package
>>>> A, it should still be able to see its own package A. I don't
>>>> think modules should be able to impact how the unnamed module
>>>> sees itself. That's a surprising situation.
>>>> 
>>>> 
>>>> The unnamed module is not a root module during resolution. If
>>>> your main class is in the unnamed module (i.e. you did java -jar
>>>> MyApp.jar rather than java -m MyApp), then the module graph is
>>>> created by resolving various root modules (what are they?
>>>> separate discussion) and only then is the unnamed module hooked
>>>> up to read every module in the graph.
>>>> 
>>>> Hope we're OK so far.
>>>> 
>>>> If some named module in the graph exports package A (more than
>>>> one module exporting A? separate discussion), then since the
>>>> unnamed module reads that named module, the unnamed module will
>>>> access A.* types from that named module.
>>>> 
>>>> It's hard to imagine the unnamed module NOT accessing A.* types
>>>> from that named module. Primarily, we need to avoid a split
>>>> package situation where code in the unnamed module sometimes
>>>> accesses A.* types from the named module and sometimes from the
>>>> unnamed module.
>>>> 
>>>> You might say, OK, let code in the unnamed module exclusively
>>>> access A.* in the unnamed module rather than exclusively access
>>>> A.* in the named module. Then you have two problems:
>>>> 
>>>> 1. There are issues for named modules in the same class loader
>>>> as the unnamed module -- such named modules MUST get A.* from the
>>>> named module rather than the unnamed module, and the class
>>>> loading mechanism is incapable of switching based on accessor.
>>>> It'll be common for named modules to exist in the same class
>>>> loader as the unnamed module, as modular JARs on the modulepath
>>>> and non-modular JARs on the classpath all end up in the
>>>> application class loader (modular JARs as named modules;
>>>> non-modular JARs jointly as the unnamed module).
>>>> 
>>>> 2. While the module system is sure that package A exists in the
>>>> named module, how would the module system possibly know that
>>>> package A exists in the unnamed module? Scanning every class file
>>>> in every non-modular JAR on the classpath at startup sounds bad.
>>>> 
>>>> Alex
>>>> 
>>>> 
>> 

Reply via email to