[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