Jigsaw prototype, take 2
David M. Lloyd
david.lloyd at redhat.com
Sun Sep 8 09:32:44 PDT 2013
On 09/06/2013 10:22 PM, Tim Boudreau wrote:
> We've worked together and I respect your judgement. That said, I have to
> disagree pretty strongly with the idea of *not* enforcing that dependencies
> be a directed acyclic graph as the default.
> Fundamentally, if you are developing two things, and there is a circular
> dependency between them, you do not have *two* things - you have one thing
> which you enjoy pretending is two. If neither can exist without the other,
> their independence is in illusion.
Our experiences with JBoss Modules has shown that there's a significant
difference between cyclic dependencies at compile time and at run time.
At run time, it is often convenient (for various reasons) to add an
implementation to its corresponding API's import list. In fact whenever
a class loader is used as a reference or start point for loading things
(particularly via ServiceLoader and its kin), it is useful to be able to
tie things together this way.
This is only one (of many) reasons why build-time dependencies and
run-time dependencies (and test-time dependencies) should be considered
> I agree that sometimes you need that sort of thing, dealing with legacy
> software and so forth. Not too long ago, I did some detangling of a
> project for a company that could only compile their software if they
> compiled against (and shipped) two historical versions of their own
> product, and not a soul there actually knew what got loaded and linked at
> runtime. Terrifying but true.
> But that being the default is the source of a *lot* of problems. And
> having to understand dependencies teaches understanding of dependencies,
> which affects how developers think about designing software.
> And explicit, non-cyclical dependencies make possible - trivial, even -
> very useful sorts of static analysis.
Unfortunately run time dependencies are anything but static. A run-time
module environment may include different implementations of things
depending on who built the environment. Just to give one example, we
provide an "org.apache.commons.logging" module at run-time, however it
is actually an alias for "org.slf4j.jcl-over-slf4j". A different
packager might make a different choice. But it is highly unlikely that
a module which uses commons-logging built against anything other than
the actual commons-logging JAR from Apache.
> I've developed a similar attitude toward Maven. Flexibility can be
> harmful, especially when there's no obvious right way to do things - it
> gives you enough rope to hang yourself. I've seen so many Make and Ant
> based projects where there was only one person in the organization who
> understood how their build system worked. Maven is inflexible in the
> extreme - there's a lot I really dislike about it. But it is utterly
Except for when it is not. On at least one - maybe more than one -
occasion, Maven changed their dependency resolution algorithm such that
transitive dependency resolution behavior could change subtly.
> Managed dependencies are like that. You *want* inflexibility as a default.
> Sure, you also want the ability to write your own classloader (IMO,
> bytecode-over-the-wire is still one of the actually interesting things
> about Java) and do what you want - the occasions are rare, but when you
> need it, you need it. But even when you *do* need it, what are you loading
> those classes *from*? If it's non-trivial and you want it to work, you
> need...its dependencies! So I suspect even when you're doing wild-west
> classloading, there are still benefits to having this stuff be explicit and
Again build time is not run time.
> I understand that for a lot of people, this JSR is about making the JDK
> leaner and meaner. But I think there are opportunities here to do things
> that dramatically reduce the maintenance cost of new software written in
> Java, and it would be a pity not to seize the opportunity to kill two birds
> with one stone.
More information about the jigsaw-dev