[External] : Re: provides and requires static ... runtime error
Alex Buckley
alex.buckley at oracle.com
Thu Apr 20 18:07:35 UTC 2023
On 4/20/2023 8:03 AM, Josiah Noel wrote:
> We're talking about a case where module Y's primary purpose is not to
> implement SPI from X, but to provide its own packages/functionality
> unrelated to X. The classes in Y that use X should not be exported, and
> should only be loaded when X service-loads them. Hence, the Y module
> will use requires static to clearly inform that the classes are required
> at build time, but not for Y's normal operation.
We understand the scenario, which involves the module system allowing
optionality not only of service providers for a given service, but also
of the service itself.
However, as Alan has been saying, `requires static` doesn't have the
precise, clear meaning that you think. When the module system sees the
directive `requires static X;` in some module Z, the module system
doesn't know the reason for the directive:
- Perhaps code in Z is annotated using annotation interfaces from X.
- Perhaps code in Z is going to reflect over the classes in X.
- Perhaps code in Z is implementing X's exported interfaces and the
owner of Z is really sure that whenever Z is resolved, X is also
resolved. (No use of ServiceLoader is intended in this item.)
You're going to say, "But that's Z, not Y! Y doesn't do any of those
things! Y uses `requires static X;` to get a light touch on a service in
X, and Y's service provision should be considered optional if X isn't
available."
But Y and Z are the same to the module system -- each directs the module
system to allow itself to be resolved even if X is not resolved. 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. If `provides` directives were treated as optional, i.e.,
ignored when the service can't be found at startup, people would say
"Why bother with `provides`? It's no more reliable than putting
everything on the classpath, when ServiceLoader throws because it can't
instantiate the service provider."
So, I hope you can see why we are extremely cautious about acceding to
requests to relax the checking of `provides`. In your scenario, Y is
pulling double duty, which makes it harder to understand overall, and
you'll benefit a lot more from breaking it up than from a more relaxed
module system.
Alex
More information about the jigsaw-dev
mailing list