[External] : Re: provides and requires static ... runtime error

Johannes Spangenberg johannes.spangenberg at hotmail.de
Sat Apr 22 00:19:57 UTC 2023


Hello, I couldn't quite follow some of the arguments regarding this 
topic. I wasn't sure if I should interfere, but I hope it will be 
helpful now that I did. :/

> But the flip side of that is that if they choose not to use X, Y would 
> just sit there, unused. Best case scenario, it would just increase 
> their image size; worst-case scenario is that it could preclude some 
> future optimisations that may require a full program analysis.

Not sure about the worst-case. The current implementation already checks 
during initialization whether the service is usable. After all, it 
throws an exception when it is not. Any optimization can just ignore the 
service provider in such case. There is no full program analysis 
required, which is not already part of every module initialization.

> To do this properly, as Alan alluded, `requires static` is 
> insufficient because the module doesn’t know where the service 
> interface is supposed to come from. Rather, we would need a new 
> specific mechanism that says “if module X is readable, then provide 
> this service”.

Why do you need the information which module provides the service 
interface? I currently don't see how this information would be helpful. 
I could also imagine cases where you want to provide an optional service 
without using `requires static`. For example, imagine a framework 
introduces a new service interface. You may want to provide an 
implementation for the service interface while keeping support for 
previous versions of the framework.

> The module system then sees that Y wants to provide a service, but the 
> module system has no idea where the service is, so fails fast at 
> startup. This is a feature, not a bug. The classpath behavior, of only 
> discovering that a service provider can't provide a service during run 
> time (because the service is missing), is not what we wanted for 
> modular services.

Does this issue really exist? The module system would already discover 
that during initialization. When the service interface is not available, 
the service provider will be ignored, there is no error (or anything 
else) later during runtime. Besides that, if the service interface is 
not available, you are unable to invoke the service loader anyway. 
Invoking the service loader requires a class instance of the service 
interface, which is not available. If you would still try to invoke the 
service loader, you would get a NCDFE at the call site of the service 
loader, the provides clause wouldn't make a difference.

I am not quite sure about the behavior if you stack multiple module 
layers on top of each other. I think the service loader should only load 
instances that implement the class from the same module layer as the 
class instance given to the service loader. Everything else would cause 
a runtime error independent of the issue we are currently discussing. In 
this case, ignoring the provides clause would be the right solution, 
even if X would be available on another module layer.

I currently see only two reasons for keeping the current behavior. The 
first one is to discourage service providers to be casually added to 
modules. You could argue that service providers should have their own 
module, so that users can add and remove them individually. The second 
reason might be the desire to fail early when the service interface was 
renamed or removed after updating X. This could be addressed by adding a 
modifier like `provides static`, there is no need to correlate the 
provides cluase with a specific `requires` clause.

> So I think a more general solution than adding a way to describe “this 
> service is conditional on the presence of X” would be to allow 
> multiple modules in a single JAR

I guess that would work as well, but it would probably be more complex 
to set up.

Best regards
Johannes



More information about the jigsaw-dev mailing list