I face the problem that the service binding option of jlink links many, many modules, none of them seems to be necessary. These modules aren't linked when the service binding option is omitted.
Questions:
My application: The application is a simple service consisting of an interface, a provider and a consumer, each packed into a separate module, called modService, modProvider, modConsumer (details below).
OS: Windows 10
Jlink without --bind-services
yields 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 would expect that in addition the module modProvider should be linked. However, see what happens (the 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 have no clue why all these modules are linked because the provider just returns a string so that no other jdk module than java.base should be needed.
Below are the 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.
jlink
so with --bind-services
😉By default jlink
does not bind services, to keep the created runtime as small as possible. That changes with --bind-services
, about which the documentation says
Link service provider modules and their dependencies.
That mirrors the behavior during regular module resolution where, after all dependencies have been resolved, all modules that provide a service used by those modules are included in the readability graph.
The same happens in your case, so all modules providing services used by java.base, modConsumer, and modService are included in the image. As you have found out, that are quite a lot.
If you want to avoid that, you have to forego --bind-services
and instead explicitly list the providers that you want to see in your image:
jlink --module-path "mods;%JAVA_HOME%\jmods"
--add-modules modConsumer,modProvider
--output myRuntime