Are modifiers `static` and `transitive` incompatible?

Piotr P. Karwasz piotr.karwasz at gmail.com
Wed Feb 7 14:14:37 UTC 2024


Hi Alan,

On Wed, 31 Jan 2024 at 16:41, Alan Bateman <Alan.Bateman at oracle.com> wrote:
> On 31/01/2024 07:47, Piotr P. Karwasz wrote:
> There is however a third option allowed:
>
> ```java
> module foo {
>     requires static transitive bar;
> }
> ```
>
> It may be surprising but they do work together. If bar is resolved then foo will read bar. If there is another module baz that requires foo (and doesn't explicitly require bar) then baz will read foo, and if bar is resolved, then baz will read bar.

Thank you for the explanation. Effectively as long as there is no path
of `requires transitive` from a root module to `foo`, the `bar module
is optional.

> We often end up with such directives, when using the
> `bnd-maven-plugin`, which maps the OSGi `resolution:=optional`
> directive to `static` and the `uses:=...` directive to `transitive`.
> If we mark a package as optional, but the package uses public types
> from `bar`, we end up with `static transitive`.
>
> Is this a bug of the plugin or does `static transitive` have a meaning?
>
> I think it's more of a case that it is fragile for modules like foo to have bar types foo API signatures.  `requires static` is okay for things like annotations with a retention policy of "source" but going beyond that means giving up a bit on reliable configuration. In the example, foo probably has a reflection guard and is careful in their use of bar types. However, foo's user if baz and the maintainers of baz are unaware of these shenanigans. This creates a risk that baz code will get a CNFE at runtime.

Yes, in the example and in practice (`log4j-core`) code that depends
on optional dependencies is in separate packages and accessed through
reflection.
This should be a runtime-only dependency, but many users do not care
about the distinction between `compile` and `runtime` scope.

If a user declares `log4j-core` as compile dependency and adds
`requires org.apache.logging.log4j.core` to their module descriptor,
the `requires static transitive` directives will cause compilation
errors, since the minimal compilation time resolution requires all
transitive dependencies of direct dependencies. That is why we
manually remove the `transitive` keyword from those dependencies.

Would it be wiser not to export packages that depend on optional dependencies?

Piotr

PS: We are facing the problems above with the legacy 2.x version,
which predates JPMS. In the new 3.x version we split the code with
optional dependencies into separate artifacts.


More information about the jigsaw-dev mailing list