is ClassLoader.loadClass() supposed to work on module-info classes?
alex.buckley at oracle.com
Sat Dec 5 00:12:16 UTC 2015
On 12/4/2015 7:52 AM, David M. Lloyd wrote:
> On 12/04/2015 09:18 AM, Alan Bateman wrote:
>> On 04/12/2015 12:59, David M. Lloyd wrote:
>>> So you're saying that if I have C depending on A, then update A or I
>>> split A and B in my distribution, I need to recompile C? I don't
>>> think that's a realistic proposition. Do I then have to recompile
>>> things that depend on C? Or things that depend on those things? How
>>> would updates work in such a scenario? Do I need to put the
>>> dependency versions of every dependency in my version string so that I
>>> can tell the difference between C compiled with the original A versus
>>> C compiled with the new A/B?
>>> It should not be necessary (and indeed it is not necessary today) to
>>> do this kind of cascading recompilation; I don't think that is
>>> something reasonable to ask of users. If they have to recompile such
>>> large swathes of their project any time anything has changed, the
>>> point of modules has been at least partially defeated.
>>> Java has a fairly clear ABI contract; a better approach would be for
>>> users to know if they've changed compatibility when they compile A, or
>>> when they split A into A and B, etc. If the ABI is the same or is
>>> forwards-compatible (i.e. only adding members), then why would a user
>>> want to recompile everything else? Is this not a red flag that the
>>> encapsulation rules are unrealistic?
>> FWIW, I also read your original mail as the wild west as it came across
>> as arbitrary refactoring of other people's modules. So best to make
>> things as clear as possible as it's just too easy to get into confusing
>> discussions here.
> Ah, yeah specifically I'm referring to splitting/merging or upgrading
> some given module in an existing system, possibly using aggregate
> modules for compatibility or alternatively updating the module
> descriptors of existing installed modules to accommodate the new layout
> (both cases seem reasonable to me, and we have done both). The phrase
> in the original email from Alex that I was responding to was "We don't
> think the module declaration will be as fluid as you do"; however our
> real-world experience shows the opposite.
> Really though you could say that splitting/merging or upgrading a
> dependency is almost-arbitrary refactoring, with the constraint being
> that the existing module's public ABI is maintained forward-compatibly.
> I know there are third party tools for testing this (I've used them);
> I think that while not *strictly* necessary, bundling such a tool in the
> JDK (regardless of how the module system ultimately behaves) is going to
> be highly desirable going forward, if possible.
Yes, the tool is a Java compiler, piggybacking on the fact that a
compiler already needs to figure out an observable universe of types to
compile the source of a program against, and in the vast majority of
Java programs, the "same" universe of types will be present at run time.
By all means have the runtime system observe different versions of those
types, but fundamentally the program's constant pool is explicit about
the types it needs.
> That's slightly
> tangential to the main idea here though, which is that an installation
> of modules may well be necessarily (and reasonably) fluid, and that
> fluidity extends to the descriptors of already-installed modules,
> because the run time graph of modules is something that is
> installation-dependent. OSGi accommodates this by using packages to
> link - basically punting the link decisions to the run time.
The allusion to Import-Package means your end goal must be to link your
program with a different version of package P today than the version
your program linked with yesterday. Maybe the different version has
debug info in the class files, or maybe the methods are mocks, or maybe
an AOP tool has injected a bunch of logging calls. Great use cases.
> We accommodate this by bundling the descriptor externally to the
> artifact so it can be easily updated by users and separately updated
> by tools (without modifying artifacts). But in any event, this
> reality *has* to be accommodated in a robust module system.
It seems like the different version of P has ended up in a
differently-named JBoss module (or OSGi bundle) than yesterday.
(Sidebar: Obviously, Jigsaw supports discovery of service providers at
run time from modules not known at compile time, but I'm assuming you're
not talking about that kind of intf-v-impl fluidity.)
This seems like an opportunity for a build tool to manage
"configurations" -- in the "debug" config, invoke javac -g P/*.java,
bundle P into the FOO-debug module, and arrange for the consumer's
module-info.class to say "requires FOO-debug" rather than "requires FOO".
But in the end, it's sugar on top of the core concept of "module
declaration" which the compiler and VM share to ensure safety (no
circular dependencies, no dependencies inducing split packages, no
access to internals, etc).
More information about the jigsaw-dev