ServiceLoader in the JDK

Jesse Glick jesse.glick at oracle.com
Thu May 24 08:08:45 PDT 2012


On 05/24/2012 10:24 AM, David M. Lloyd wrote:
> Rarely, if ever, do you want to
> find every implementation of a service in the entire universe.

Not the entire universe, but the set of modules loaded in the current module configuration (~ application). That is what Jigsaw "requires service" requests. So if that 
system is wanted, there needs to be an API call implementing that.

> In reality you most often want to find services relative to a specific
> module/class loader - most often it's the running application

That is exactly what "requires service" means - all services in the running application. Which need not map at all to any particular ClassLoader. (While it might be a 
particular Module, an "application entry point" module, that module's ClassLoader will _not_ generally be able to load all the app's services unless it happens to declare 
direct dependencies on every service provider.)

> sometimes it's the API module itself

Probably pointless, since that would only be able to load services defined in the same module; you might as well statically enumerate them.

> or something else altogether.

In custom cases you ought to be able to use the existing ServiceLoader.load(Class,ClassLoader) with the same semantics as in JDK 7, i.e. loader.getResources(PREFIX+svc). 
It is debatable whether this method should also load "provided services" from Jigsaw modules which are visible to the supplied ClassLoader if that is in fact a 
ModuleClassLoader - that would enable you to load a subset of available services according to a subgraph of the application's dependency graph, conceivably useful but 
rather more complex and probably an advanced usage.

> the TCCL is still a valid concept - perhaps more so than ever - with modules and should continue to be supported to mean "the current application".

TBD. It is used in some existing module systems (not OSGi AFAIK) since it sort of works and there is nothing clearly superseding it. It is not entirely clear what types 
and resources should be visible to it, and it is even less clear how it should behave when multiple modules define a class with the same FQN, which ClassLoader cannot 
represent. (ClassLoader _can_ represent multiple resources with the same path, but as I mentioned earlier this is not good enough for ServiceLoader since getResources 
returns a list of URL's with no indication of the "defining loader".)

> Only in rare cases do you really want to have a concept of JVM-wide service implementations

To the contrary I would say this is the normal case for applications not running in a special multitenancy container such as EE. If you do have multiple apps in the JVM 
then (as mentioned in my last message) it is up to the module system to somehow ensure they do not interfere with one another, such as by offering distinct Module/Class 
instances, or using some implicit context like ThreadGroup. Looking for a subset of those service implementations available within the "current" application is another 
use case but probably more specialized.

> you cannot assume that there is only one class with a given name installed in the system

No, you cannot, and correct implementations of service loading will not make such an assumption. JDK 7's ServiceLoader is broken in this regard in two ways: (1) absent a 
richer ClassLoader.getResources, it cannot tell which loader defined a service, so it cannot be sure to load the implementation class from that same loader, mishandling 
multiple copies of an implementation; (2) it fails to verify that a candidate implementation is actually assignable to the supplied interface, so it produces CCEs if you 
have multiple copies of the interface. In NetBeans we have a replacement service loader which fixes both these bugs.



More information about the jigsaw-dev mailing list