Layers and NoClassDefFoundError

Peter Levart peter.levart at gmail.com
Tue Oct 13 12:49:00 UTC 2015



On 10/13/2015 10:59 AM, Nicolai Parlog wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA256
>
>   Hi Alan.
>
>> Can you paste in the code that creates the ModuleClassLoader for
>> the second Layer? I'm curious to see if you have used the 2-arg
>> constructor to specify the first as the parent.
> The code was the same for both:
>
> 	ClassLoader loader =
> 			new ModuleClassLoader(configuration);
>
> After your mail I changed it for the second layer so it uses the first
> layer's ModuleClassLoader. Now everything works like a charm. Thx!
>
> Follow up question: In this case I constructed the first layer myself
> and only used one class loader for it, which I hence had readily
> available to pass to the second layer.
>
> What happens if this is not the case? I know about 'Layer.findLoader'
> but how would I choose a loader for the second layer? E.g. if I used
> several loaders or the first layer or did not even create it myself
> and have no idea which and how many loaders it contains.

I don't know for sure, but I see a Layer as a combination of 2 aspects 
that have to be soundly aligned:

- readability graph of modules
- delegation of class-loaders

For example, say you have a layer with 2 modules: moda & modb and two 
ClassLoaders loadera & loaderb.

If loaderb is a child of loadera and moda is loaded by loadera while 
modb is loaded by loaderb, then the following reads edge is possible:

- modb reads moda

but the following is not:

- moda reads modb


So to answer your question, on which loader in a parent layer to base 
the child class-loader in a child layer. The one that can (by delegation 
and by itself) load classes in modules that modules in child layer 
loaded by child class loader depend on.

For example. You could choose extension class-loader as the parent of 
your child loader in the child of boot layer, but then modules loaded by 
child loader would not be able to depend on modules loaded by system 
class loader (the app class loader).

So when you attach a child layer to a parent layer, you have to know 
something about the structure of class loaders in the parent layer and 
which modules are loaded by which of them. If parent layer is a simple 
delegation chain of loaders (not a tree with multiple branches), then 
the safest loader to choose as the parent is the single "leaf" loader. 
If the tree in parent layer has multiple branches, you might need to 
extend those branches to the child layer using separate "peer" loaders 
in the child layer, but of course, modules in separate loader delegation 
branches can then not depend on each other although they are all in the 
same layer.

Have I got the picture right?

Regards, Peter

>
>> The beforeFinder is for overriding a module with a different
>> version. It sounds like you have ended up trying to override the
>> modules in the boot layer and you probably don't want to do that.
> That makes sense, thanks.
>
>   so long ... Nicolai
>
>
>
> On 12.10.2015 23:24, Alan Bateman wrote:
>>
>> On 12/10/2015 21:44, Nicolai Parlog wrote:
>>> :
>>>
>>> For the first layer 'parentLayer' is 'Layer.boot()', for the
>>> second it's the first.
>> Can you paste in the code that creates the ModuleClassLoader for
>> the second Layer? I'm curious to see if you have used the 2-arg
>> constructor to specify the first as the parent.
>>
>>> Then I add a read edge from the module that runs all this to the
>>> one in the second layer that contains the code I actually want to
>>> execute. Finally I access the code I actually want to run (in the
>>> second layer) and invoke it. I then get a NoClassDefFoundError
>>> for a class that is present in the first layer.
>>>
>>> I tried adapting the 'parentLayer' to be used as the
>>> 'beforeFinder' in 'Configuration.resolve' instead of
>>> 'ModuleFinder.empty()' but that gave me a
>>> 'LayerInstantiationException' ("Module java.base is already
>>> defined").
>> The beforeFinder is for overriding a module with a different
>> version. It sounds like you have ended up trying to override the
>> modules in the boot layer and you probably don't want to do that.
>>
>> -Alan.
>>
> - -- 
>
> PGP Key:
>      http://keys.gnupg.net/pks/lookup?op=vindex&search=0xCA3BAD2E9CCCD509
>
> Web:
>      http://codefx.org
>          a blog about software development
>      http://do-foss.de
>          Free and Open Source Software for the City of Dortmund
>
> Twitter:
>      https://twitter.com/nipafx
>
> Diaspora:
>      nipa at pod.geraspora.de
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v2
>
> iQIcBAEBCAAGBQJWHMfUAAoJEMo7rS6czNUJ0Z8QAJkl/y86G7mUj6cSnruuFmIl
> 54bME/aAWN5ljpQW6/Zexdy7CgRtSOipQBo2uxYUzO56mU17l7b+sigBtDTj7h/3
> i1I4e6cyubKWTWWZ3tJFltRJJXEnz5v5Ey15v7mopepm9v0dsP3HDjDHzTJSpOmX
> BvHIdUSS7qmqU+U3IePPI51sTPGv/JjgC/chYxCZgZ1Nzl6j+Rp4vuUSRbzAbNg6
> jyVNId8MRr32LRumgmcdQhOe6unrzNLaqElu89CyKkx/M885T2xaYpLTlqIPxAEV
> dFRzvVGcM/vKX/iuqG42yUyqkI133T4YFp1yZxTjT3/9HajJ6uepFPR5UaILIawY
> /VTg1n1ibawxzv2Lv0CEc/qq9qGJmEDe+wIDmYLfNhgNn9ZmNMrHEuFGjCp/DxBE
> lBhtPu4/3/aNvAxWPAUTn0pxGCBsefZOz8EoeJJTwvwick8TuuN+DS7YBUucwoCZ
> Cq8i8wJS/ygwIzQy3TzBd/CKfnn4r8AHc/Iabg3vYtwB4rxBniafXsSXjdk2Uot+
> ycis3qNrv5dFi8YPBqM29mKQdHbstYOr0EPGIMBdyPDDfG+nX9qZ5uN4411xsQf7
> 4bzfEUvz5sCcorE28dV63e+QVsNyPQ6mjya8dPULJhRY61A3TQXZRUuGmd+9YVFM
> FnGcuzoCyR95qj4NQt7p
> =K4+T
> -----END PGP SIGNATURE-----
>



More information about the jigsaw-dev mailing list