Jlink: service link links many unnecessary modules

I ran into a problem that the option of binding a service to jlink binds many, many modules, none of them seem necessary. These modules are not connected if the service binding option is omitted.

Questions:

  • Q1: Do you see the same behavior in your environment?
  • Q2: Is this a mistake or a desired behavior?
  • Q3: Why are all these modules connected?

My application: the application is a simple service consisting of an interface, a provider and a consumer, each of which is packaged in a separate module called modService, modProvider, modConsumer (see below for more details).

OS: Windows 10

Jlink without --bind-services gives the expected result:

 jlink --module-path "mods;%JAVA_HOME%\jmods" --add-modules modConsumer --output myRuntime java --list-modules java.base@9 modConsumer modService 

When the --bind-services option is applied, I expect the modProvider module to be connected. However, see what happens (three custom modules are at the end):

 jlink --module-path "mods;%JAVA_HOME%\jmods" --bind-services --add-modules modConsumer --output myRuntime java --list-modules java.base@9 java.compiler@9 java.datatransfer@9 java.desktop@9 java.logging@9 java.management@9 java.management.rmi@9 java.naming@9 java.prefs@9 java.rmi@9 java.scripting@9 java.security.jgss@9 java.security.sasl@9 java.smartcardio@9 java.xml@9 java.xml.crypto@9 jdk.accessibility@9 jdk.charsets@9 jdk.compiler@9 jdk.crypto.cryptoki@9 jdk.crypto.ec@9 jdk.crypto.mscapi@9 jdk.deploy@9 jdk.dynalink@9 jdk.internal.opt@9 jdk.jartool@9 jdk.javadoc@9 jdk.jdeps@9 jdk.jfr@9 jdk.jlink@9 jdk.localedata@9 jdk.management@9 jdk.management.cmm@9 jdk.management.jfr@9 jdk.naming.dns@9 jdk.naming.rmi@9 jdk.scripting.nashorn@9 jdk.security.auth@9 jdk.security.jgss@9 jdk.unsupported@9 jdk.zipfs@9 modConsumer modProvider modService 

I don’t know why all of these modules are connected, because the provider simply returns a string, so no jdk module other than java.base is needed.

The following are Java artifacts:

 package test.service; public interface HelloService { public String sayHello(); } 

 package test.provider; import test.service; public class HelloProvider implements HelloService { @Override public String sayHello() { return "Hello!"; } } 

 package test.consumer; import test.service; import java.util.ServiceLoader; public class HelloConsumer { public static void main(String... args) { ServiceLoader.load(HelloService.class).forEach(s -> System.out.println(s.sayHello())); } } 

 module modService { exports test.service; } module modProvider { requires modService; provides test.service.HelloService with test.provider.HelloProvider; } module modConsumer { requires modService; uses test.service.HelloService; } 

Any help is appreciated.

+5
source share
2 answers

Short version

  • Q1: Yes.
  • Q2: Desired Behavior
  • Q3: Because you said jlink , so with --bind-services πŸ˜‰

Long version

By default, jlink does not bind services to keep the created runtime as small as possible. This is changed using --bind-services , which the documentation says

Associate vendor service modules and their dependencies.

This reflects the behavior at regular resolution of the module, where after removing all the dependencies, all modules that provide the service used by these modules are included in the readability schedule.

The same thing happens in your case, so all modules providing services used by java.base, modConsumer and modService are included in the image. As you found out, this is quite a lot.

Decision

If you want to avoid this, you need to abandon --bind-services and instead explicitly specify the providers that you want to see in your image:

 jlink --module-path "mods;%JAVA_HOME%\jmods" --add-modules modConsumer,modProvider --output myRuntime 
+3
source

As indicated in the jlink documentation .

 --bind-services 

Associate vendor service modules and their dependencies.

further, the sample in the same illustrates that

Option

associates the modules allowed from the root modules with the binding service; see the Configuration.resolveAndBind Method.

From your previous command, the root module and those that were resolved in your default module graph:

 java.base@9 modConsumer modService 

and, in addition, the remaining modules listed using the --bind-services flag are resolved using the java.base module.

I would expect that in addition the modProvider module should be connected

As suggested by nicolai , you can add a provider module and make sure that it is also enabled in the module graph.

  --add-modules modConsumer,modProvider 

<sub> Thoughts aloud. 1. The current supplier search process is iterative. 2. Is it possible to indicate the modules for which you need to search explicitly when searching for service providers? Sub>

+5
source

Source: https://habr.com/ru/post/1274974/


All Articles