Still driving off the cliff
Alan Bateman
Alan.Bateman at oracle.com
Thu Feb 23 04:16:14 PST 2012
On 22/02/2012 20:36, David M. Lloyd wrote:
> :
> Just to clarify I was talking about the selector provider API, not the
> filesystem API (I'm old school like that).
SelectorProvider is a case where the default provider is rarely (or
ever) replaced but I don't mind using it as an example.
Like other APIs it defines a way to override the VM-wide provider (via a
system property in this case). Assuming the override mechanism is not
used then it uses ServiceLoader in an attempt to find a provider
implementation. If someone "installs" several implementations into the
extensions directory then one of them will be used, exactly which one is
not defined. An alternative would be to put them on the system class
path, in which case it's more predictable. If ServiceLoader doesn't
locate any provider implementations there is a fallback/default
implementation. In the case of the JDK then we typically have a default
implementation anyway and ServiceLoader is just used for cases where
folks want to use alternative implementations.
Now move to the modules world when there isn't a boot or system class
path or extensions class loader. I've packaged my SelectorProvider
implementation into a module and I'd like it to be used at runtime
without using the override mechanism. The way it works currently in
Jigsaw is that you install the module with the service provider and it
will be linked as a service supplier to modules that require this
service. In this case, it's the jdk.base module that requires this
service. Clearly if someone installs another module that also provides a
SelectorProvider implementation then it's like installing into the
extensions directory in the current world; one will be chosen and
there's a way to override it. In the implementation then the order is
stable and doesn't change between runs.
>
> But the modular world *is* class loader centric, that's my whole
> point. Java is already 80% of the way towards being modular as of
> Java 7. All it is missing is a multiple-delegate base class loader and
> a module loader concept which creates class loaders for modules. A
> 1:1 module:class loader mapping is completely natural on many levels,
> and I have yet to see a compelling argument to the contrary. And in
> this model ServiceLoader works like a champ.
I don't get your comment on being 80% there. The work we did in JDK7 was
mostly on cleaning up dependencies in the implementation in preparation
for the modularize effort.
With Jigsaw then it's usually a 1-1 mapping between module and class
loaders but we do have complications in the platform and it remains to
be seen where that goes. In addition I'm not sure where the class loader
relationship will be specified or not.
>
> My point is that by recognizing that a class loader *already* is a
> module by another name, you should realize that no new API is needed
> and no dual-mode situation should even arise.
>
> :
> We already have that today. Granted TCCL is considered ugly by some,
> but all it's really missing is a clear definition of what it *means*.
> That's what most users (and classically, framework developers) don't
> get. It *means* your current application module. That's the only
> meaning that makes any sense. And there's no way that TCCL is going
> to go away just because you deprecated it and created "new" mode
> versus "old" mode. It just needs to be formalized. On app startup,
> set TCCL to the main application module's class loader. In JavaEE,
> set it to the currently executing deployment. Consistent and simple.
> And it fits the existing java.util.ServiceLoader like a glove.
>
As I said, I think ServiceLoader has to change. The loadInstalled(Class)
method is specified to use class loaders that don't make sense with
modules. The load(Class) method is specified to use the
threadContextClassLoader but what if that has been set to null or
ClassLoader.getSystemClassLoader (we have many of these in JDK). Same
thing with load(Class,ClassLoader). For now these methods are using the
module class loader of the caller. If the caller's module declares that
it requires the service then it gets back a ServiceLoader to iterate
over the implementations of that service.
On the thread context class loader then my view is that it was a
mistake. It's been a continuous source of problems, security issues
included.
-Alan.
More information about the jigsaw-dev
mailing list