[External] : Re: Inconsistency with service loading by layer or by class loader

Ron Pressler ron.pressler at oracle.com
Mon Dec 16 17:56:17 UTC 2024



> On 16 Dec 2024, at 17:17, David Lloyd <david.lloyd at redhat.com> wrote:
> 
> The model I'm working with is such that we are loading every single module (whether they are within our container or the user's application) into a separate layer, as has been previously recommended as the way to meet requirements like ours, with our class loaders handling all inter-module linkage concerns. Everything works exactly as we want in this scenario: modules are able to be lazily loaded and linked (just like classes); our integrity constraints are enforced locally per module on demand, rather than globally across the whole layer (again, just like classes); and, we get our nice stack traces and encapsulation behaviors. However there is one exception, and that is that service loading does not work for any module, since no modules can find their implementations, regardless of what we do with class loading. This is what I'm trying to address.

Ok, thank you! Indeed, if a dynamic container is designed to load every module in a separate layer then ServiceLoaders in libraries may not work unless the container is able to put a library’s service providers in the same layer as the library. 

Now, if you’re not interested in Alan’s suggestion, then there’s not much I can add.

I can say that I’ve seen similar problems arise with virtual threads. Some projects wanted to get the benefit of virtual threads under the condition that nothing else in their architecture, algorithms, or deployment would have to change, and that’s just not possible sometimes (e.g. to get the benefit of virtual threads you need high concurrency, and if the rest of your system is designed and deployed to ensure that every server only ever experiences low concurrency then you won’t enjoy the benefits of virtual threads). Similarly, modules were not designed to match every possible non-modular design (e.g. they also forbid circular dependencies), especially every elaborate dynamic loading design. That wasn’t the intent.

As another side note, I will also say that not a single invariant written in Java can have integrity without modules’ strong encapsulation. Even properties such as “strings are immutable” cannot be trusted, let alone “this private method is never called unless some precondition holds”. In particular, class loader isolation only offers encapsulation in a very approximate and rather weak sense.

In short, I’m not discounting the difficulty you’ve encountered, but if you want to enjoy modules’ capabilities as they currently work, you may want to consider a different design.

Is Quarkus also experiencing that difficulty?

— Ron


More information about the jigsaw-dev mailing list