<div dir="ltr"><div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">If I have a module layer A containing module X that is registered to some class loader L, *or* a class within the unnamed module of L, and I create a new layer B contains module Y which is also registered to L, and B contains modules which provide services, then once this layer is created, loading services from class loader L will begin to find all service providers in B (even those not in Y) in addition to those in A. This happens dynamically at the time the new layer is created, even if B and A are sibling/cousin layers. This behavior exists today.</div></div><div><br></div><div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Sometimes it is desirable to load a plugin (for example) where the module(s) in the plugin provide services but the plugin should be loaded into a layer that is isolated from (i.e. a sibling to) the service-consuming layer, which is generally a private implementation layer or a peer plugin. Note that the service type would be in a parent layer or otherwise findable by both layers.</div><br></div><div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Thanks to the above behavior, this can be accomplished (poorly) today by dynamically generating a layer with a "holder" module, containing one generated class per service provider defined in B which is declared to provide the corresponding service type. Each generated class would contain a `provider` method which accesses the corresponding "real" service provider and instantiates it according to the service loader specification. The "holder" module is then mapped to class loader L, allowing L to then indirectly load the service implementations in the sibling layer.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Sometimes it is possible to use a simpler approach where layer B contains a "bogus" empty module which is registered with A. This works when B is defined after A. But this would not generally be the case.</div><br></div><div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">This is all unwieldy. The purpose of 8346946 [1] is to allow a simpler way to directly register a layer with a custom class loader for service loading, without defining an extra bogus module or a fake bridge layer. There might be other ways to make this possible than the approach proposed in the current version of the PR [2]. For example, in order to ensure that I control both the class loader and the module layer in question, the protected method on `ClassLoader` could accept a `ModuleLayer.Controller`, ensuring that callers have control over both objects. Other solutions may be possible as well.</div><br></div><div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">[1] <a href="https://bugs.openjdk.org/browse/JDK-8346946">https://bugs.openjdk.org/browse/JDK-8346946</a></div></div><div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">[2] <a href="https://github.com/openjdk/jdk/pull/22905">https://github.com/openjdk/jdk/pull/22905</a></div><br></div><span class="gmail_signature_prefix">-- </span><br><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr">- DML • he/him<br></div></div></div>