Avoiding same-package conflicts

Alex Buckley alex.buckley at oracle.com
Tue Nov 3 21:28:29 UTC 2015


On 11/3/2015 1:56 AM, Jochen Theodorou wrote:
> On 02.11.2015 22:03, Alex Buckley wrote:
> For groovy.util the case is more problematic. Moving GroovyTestCase into
> a new package would for example break an estimated 95% of our test
> cases. What will most likely happen is, that the test module merges with
> the base module thus pulling in "optional" dependencies like JUnit 3...
> which is in conflict with us trying to slim down the base runtime even
> more, to for example give the android version an easier standing. We
> have been thinking about for example moving the compiler into a separate
> jar. But splitting something something as tightly coupled as that will
> cause numerous same-package conflicts... Just to give an example... Eval
> is a class in groovy.util and used for example like this:
>
>   assert 10 == Eval.me(' 2 * 4 + 2')
>   assert 10 == Eval.x(2, ' x * 4 + 2')
>
> Of course this will call the compiler.. but what use is there to make a
> groovy-base and a groovy compiler jigsaw style module, if they strongly
> depend on each other anyway?

groovy-compiler will obviously have a hard dependency on groovy-base, 
but you can avoid groovy-base having a hard dependency on 
groovy-compiler by using services. Of course this assumes a suitable 
split between the interface of your compiler and its implementation.

Even the java.base module is very open to external providers -- see the 
Services column of 
http://cr.openjdk.java.net/~mr/jigsaw/ea/module-summary.html#java.base 
-- for example, "uses java.net.ContentHandlerFactory" can be provided by 
java.desktop, and "uses java.security.Provider" can be provided by 
java.naming, java.security.jgss, et al.

> Anyway... my intension was to give an example of how some people divide
> a broad library into "modules" and how it does not fit the "one module
> per jar, no exported name space duplication" idea. And you just
> confirmed it with the initial modularization of JavaFX.

Yes. We were clear at JavaOne that 1:1 migration -- one module per JAR 
-- is just one possibility among many. I actually expect the main 
obstacle to 1:1 migration to be not duplication of exported packages but 
rather cycles between classes in the JARs.

>>> also... there is a automated meta class lookup system, that is based on
>>> the package name with a prefix. So someone could provide a meta class
>>> for java.util.ArrayList, while another does this for LinkedList. If they
>>> are using modules, they cannot be loaded at the same time. Granted, I
>>> don't like this mechanism, and I am looking for ways to deprecate it in
>>> the near future, but it is another example of same-package conflicts.
>>
>> Does this mean a Groovy meta class can currently be defined as a class
>> in the java.* run-time package of the bootstrap loader?
>
> The class would be groovy.runtime.metaclass.java.util.ArrayListMetaClass
> and doesn't have need the bootsrap loader for this of course. We
> actually always avoided implementing logic that depends on being in the
> bootstrap loader.

That's good. Still, as you said, the meta classes for java.util.{A,B} 
might live in different modules, so each of those modules will try to 
export g.r.m.java.util to the same consumer.

One option for the Groovy runtime is to special case its meta class 
package hierarchy by arranging for g.r.m.** classes to be defined by, 
and exported from, a special module that the runtime generates; the 
runtime would set up readability between this module and the user 
modules that "thought" they were defining and exporting g.r.m.**.

You can see a flavor of this technique in the "dynamic module" created 
by Java's Core Reflection when you proxy certain interfaces -- see 
"Package and Module Membership of Proxy Class" in 
http://cr.openjdk.java.net/~mr/jigsaw/spec/api/java/lang/reflect/Proxy.html.

Alex


More information about the jigsaw-dev mailing list