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