ServiceLoader.load(Class, ClassLoader) does not load services exposed in modules and loaded by parent CL

Peter Levart peter.levart at gmail.com
Wed May 23 15:55:51 UTC 2018



On 05/23/2018 05:39 PM, Peter Levart wrote:
>
>
> On 05/23/2018 05:08 PM, Alan Bateman wrote:
>> On 23/05/2018 15:29, Peter Levart wrote:
>>> :
>>>
>>> Maven seems to load plugins in a child class loader of the "system" 
>>> (application) class loader and also sets this class loader as thread 
>>> context class loader. ServiceLoader does not find any 
>>> ScriptEngineFactory services when using this class loader.
>>>
>>> The question is: Is this maven plugin's fault? Should the plugin 
>>> load services using explicit "system" (application) class loader or 
>>> should the ServiceLoader lookup strategy climb the class loader 
>>> delegation chain and include service providers that are registered 
>>> in system Layer too if given class loader is a descendant of 
>>> "system" (application) class loader?
>>>
>>> Before JDK 9, using an child class loader of "system" (application) 
>>> class loader would locate system services, but since JDK 9, they are 
>>> invisible to such child class loaders. Is this intentional? Would it 
>>> be wrong if the lookup strategy was more "backwards compatible" ?
>> Are you sure the Maven plugin is setting the TCCL to a child of the 
>> application class loader? Any chance that the parent is null which 
>> would bypass the platform (formerly the extension) class loader?
>>
>> -Alan
>
> I thought so. This is what debugger told be me about TCCL (debugger 
> calls .toString() on it by default):
>
> ClassRealm[plugin>com.marand.misc:misc-mojo-git:1.24, parent: 
> jdk.internal.loader.ClassLoaders$AppClassLoader at 1de0aca6]
>
> But now that you asked specifically, I also checked the instance and 
> evaluated .getParent() on it and got null ?! toString is a damn liar!
>
> It seems that Maven class loaders don't follow standard delegation 
> model and so JDK can't climb the chain. Sorry for not checking this 
> before. There's nothing JDK can do about it, I belive.
>

Well, there could be something. But I don't know whether it would be a 
good idea. Platform class loader could present services registered in 
the boot ModuleLayer as "virtual" resources at standard 
META-INF/services resource path locations. ServiceLoader could then 
locate them via the ClassLoader.getResources() call even if the class 
loaders involved didn't follow standard delegation model, but providing 
they would delegate the getResources() invocation in their non-standard 
way. Maven class loader seems to delegate to application class loader, 
but not via the standard getParent().

Would this be too messy?

Regards, Peter



More information about the core-libs-dev mailing list