provides and requires static ... runtime error

Rob Bygrave robin.bygrave at gmail.com
Tue Apr 18 10:50:30 UTC 2023


*> `requires static` is more for use-cases like annotations that do not
need to be present at run-time*

I am aware that annotations have a retention policy but otherwise why are
we specifically saying "like annotations" here as opposed to just saying
"types"?


*> I understand there is a temptation to compare `requires static` with
optional dependences in Maven but they are not the same thing. `requires
static` is more for use-cases like annotations that do not need to be
present at run-time. It could of course be extended but it's a slippery
slope that ultimately amounts to giving up on reliability.*

Background:  I also maintain Ebean ORM which is made up of 20+ modules (+
3rd party dependencies) and works with classpath and module-path. A quick
search for "requires static" there shows me 25 uses of requires static (192
requires clauses in total on the core modules, I'm suggesting this is a
non-trivial use of module-path that uses a decent amount of requires
static).

Of those 25 requires static, 5 of those are dependencies on optional
annotations and 20 are optional dependencies that are *NOT* annotations.
They all match to maven optional true dependencies (self fulfilling I know).

For all these cases requires static has worked exactly as I expect and
exactly the same with classpath and module-path. There have been no
issues.  No issues when the requires static was for annotations and no
issues when the requires static was for normal types (not annotations).


> *do not need to be present at run-time.*

So for ebean orm, it is using [requires static / optional at runtime] types
that are both annotations and normal class types and they are all
potentially not present at run-time. There is a suggestion there is a
slippery slope for the requires static types that are not annotations? I'm
wondering why? As in, optional dependencies have been reasonably
extensively used and there has been no issue hit here with module-path and
requires static and everything has worked as expected*.

*Except the issue noted in this thread which imo isn't an issue with
requires static. That is, I'm now aware of the issue with ServiceLoader in
module-path not working when provides p.S is via requires static (unlike
classpath) ... but in my mind that issue isn't really an issue with
requires static per say but instead it is an issue with the runtime module
resolution (by not allowing *provides p.S* to be optional).


> *It could of course be extended *

Extended? What is wrong with how requires static works now? How
are you suggesting it could be extended and for what purpose?


> *but it's a slippery slope that ultimately amounts to giving up on
reliability.*

Well, optional dependencies by their nature are sometimes dynamically
determined at runtime which isn't ideal but also not difficult or new. Can
you give an example of what you mean by this?


Thanks, Rob.

On Tue, 18 Apr 2023 at 20:05, Alan Bateman <Alan.Bateman at oracle.com> wrote:

>
> On 17/04/2023 15:20, Rob Bygrave wrote:
>
> *:*
>
>
> > *is it reasonable to consider that ServiceLoader is the *only* vector
> by which the implementation class will be instantiated? *
>
> In my view this is expected and imo I get there by thinking in the
> opposite direction from the provides p.S type to the requires static rather
> than the other way around. That is, the p.S type is only available via
> requires static hence it is expected to potentially not exist at runtime in
> the module-path. That is, if p.S was expected to exist at runtime it would
> be "read" via a requires or requires transient clause and not via a
> requires static - *the use of requires static for this case is explicit
> and intentional*.
>
> In using requires static ... imo we are explicitly going out-of-our-way to
> say "the types here might not be available at runtime" and the classic case
> for this as I see it is this case of providing an optional service, that
> will only be service loaded if the user of that service is in the classpath
> / module-path. *IF* the module that is the user of a service is in the
> classpath / module-path then that module will ensure that the p.S type is
> in the module-path.
>
>
> In your example, module io.avaje.config declares that it provides an
> implementation of io.avaje.inject.spi.PropertyRequiresPlugin. There is
> nothing to connect this to `requires static io.avaje.inject`. The module
> system would need to search "far and wide" for io.avaje.inject to see if
> exports io.avaje.inject.spi to io.avaje.config, otherwise there is no way
> for it to know that the "missing package" is in a module that is not
> required to be present at run-time. In other words, `requires static io.avaje.inject`
> does not convey to the module system that io.avaje.inject exports
> packages with service types.
>
> I understand there is a temptation to compare `requires static` with
> optional dependences in Maven but they are not the same thing. `requires
> static` is more for use-cases like annotations that do not need to be
> present at run-time. It could of course be extended but it's a slippery
> slope that ultimately amounts to giving up on reliability. In this case, it
> amounts to giving up on a post resolution check and allowing all service
> providers to have a dangling reference to a service type.
>
> -Alan
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/jigsaw-dev/attachments/20230418/c687e1e9/attachment-0001.htm>


More information about the jigsaw-dev mailing list