jlink:服务绑定链接许多不必要的模块

时间:2018-01-26 19:18:03

标签: java java-9 jigsaw jlink

我面临的问题是jlink的服务绑定选项链接了许多模块,似乎没有必要。省略服务绑定选项时,这些模块不会链接。

问题:

  • Q1:您是否在环境中看到了相同的行为?
  • Q2:这是一个错误还是一个理想的行为?
  • 问题3:为什么所有这些模块都链接在一起?

我的应用程序:应用程序是一个简单的服务,由接口,提供者和使用者组成,每个服务都打包到一个单独的模块中,称为 modService modProvider modConsumer (详情如下)。

操作系统:Windows 10

没有 --bind-services的Jlink 会产生预期的结果:

jlink --module-path "mods;%JAVA_HOME%\jmods"
    --add-modules modConsumer
    --output myRuntime

java --list-modules
java.base@9
modConsumer
modService 

当应用--bind-services选项时,我希望另外还应链接模块 modProvider 。但是,看看会发生什么(三个自定义模块在最后):

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

我不知道为什么所有这些模块都被链接,因为提供者只返回一个字符串,因此不需要其他jdk模块而不是java.base。

以下是Java工件:

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; 
} 
  

感谢任何帮助。

2 个答案:

答案 0 :(得分:4)

正如jlink documentation中所述。在

--bind-services 
  

链接服务提供商模块及其依赖项。

此外,同样的样本说明了

  

选项将链接从根模块解析的模块与服务   捆绑;看到了   Configuration.resolveAndBind   方法

根据您之前的命令,默认情况下,根模块和模块图中已解析的模块为:

java.base@9
modConsumer
modService

此外,使用--bind-services标志时列出的其他模块通过java.base模块解析。

  

我希望另外模块modProvider应该是   联

根据建议by nicolai,您可以添加提供程序模块,并确保在模块图中也解析它。

 --add-modules modConsumer,modProvider

<子> 大声思考。 1.当前查找提供程序的过程是迭代的。 2.是否可以在明确查找服务提供商时指定要查找的模块?

答案 1 :(得分:4)

短版

  • Q1:是的。
  • Q2:期望的行为
  • 问题3:因为您使用jlink
  • 告诉了--bind-services

长版

默认情况下,jlink不绑定服务,以使创建的运行时尽可能小。这随--bind-services的变化而变化,the documentation表示

  

链接服务提供商模块及其依赖项。

这反映了常规模块解析期间的行为,在解决了所有依赖关系后,所有提供这些模块使用的服务的模块都包含在可读性图中。

在您的情况下也是如此,因此提供 java.base modConsumer modService 所使用的服务的所有模块都包含在图片。正如你所知,这是相当多的。

解决方案

如果您想避免这种情况,则必须放弃--bind-services,而是明确列出您希望在图片中看到的提供商:

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