JPMS是否支持来自META-INF的服务/自动模块服务?

时间:2018-11-05 09:00:27

标签: java log4j2 slf4j java-9 java-module

Here,您可以找到有关自动模块的以下内容:

  

模块系统还扫描META-INF /服务并使其自动   模块提供其中命名的服务。一个自动模块是   假定允许使用所有服务。

但是,我有以下情况。我想在JPMS中将log4j2与slf4j一起使用。为此,log4j-slf4j-impl-2.11.1.jar必须向slf4j-api-1.8.0-beta2.jar提供JPMS服务。 log4j的开发人员将log4j-slf4j-impl-2.11.1.jar作为自动模块,并通过META-INF / services提供了服务。但是,它不起作用,它给出以下内容:

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/logging/log4j/Logger
    at org.apache.logging.log4j.slf4j@2.11.1/org.apache.logging.slf4j.SLF4JServiceProvider.initialize(SLF4JServiceProvider.java:53)
    at org.slf4j/org.slf4j.LoggerFactory.bind(LoggerFactory.java:153)
    at org.slf4j/org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:141)
    at org.slf4j/org.slf4j.LoggerFactory.getProvider(LoggerFactory.java:419)
    at org.slf4j/org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:405)
    at org.slf4j/org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:354)
    at org.slf4j/org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:380)
    at Log4j2Slf4jJdk11/com.temp.NewMain.<clinit>(NewMain.java:12)
Caused by: java.lang.ClassNotFoundException: org.apache.logging.log4j.Logger
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
    ... 8 more

我决定将模块信息添加到log4j-slf4j-impl-2.11.1.jar并通过provides ... with..以JPMS方式导出服务。问题解决了-我什么也没得到NoClassDefFoundError。这是问题的link

所以我的问题:

  1. JPMS是否在META-INF中支持服务/自动模块服务?
  2. 如果是,那么如何解释这种行为?

编辑 共有5个模块:

slf4j-api-1.8.0-beta2.jar  // name: org.slf4j
log4j-slf4j18-impl-2.11.1.jar // name: org.apache.logging.log4j.slf4j
log4j-core-2.11.1.jar // name: org.apache.logging.log4j.core
log4j-api-2.11.1.jar // name: org.apache.logging.log4j
log4j2-slf4j-jdk11-1.0-SNAPSHOT.jar // name: Log4j2Slf4jJdk11

变量1 如果在log4j-slf4j18-impl-2.11.1.jar具有META-INF/services时运行--show-module-resolution,则会得到以下输出(我将完整路径替换为{{1 }}):

...

变量2 如果在... root Log4j2Slf4jJdk11 file:.../log4j2-slf4j-jdk11-1.0-SNAPSHOT.jar Log4j2Slf4jJdk11 requires org.slf4j file:.../slf4j-api-1.8.0-beta2.jar jdk.compiler binds org.apache.logging.log4j.core file:.../log4j-core-2.11.1.jar automatic org.slf4j binds org.apache.logging.log4j.slf4j file:.../log4j-slf4j18-impl-2.11.1.jar automatic 具有log4j-slf4j18-impl-2.11.1.jar时运行--show-module-resolution,则会得到以下输出:

module-info

在变量1中,来自... root Log4j2Slf4jJdk11 file:.../log4j2-slf4j-jdk11-1.0-SNAPSHOT.jar Log4j2Slf4jJdk11 requires org.slf4j file:.../slf4j-api-1.8.0-beta2.jar jdk.compiler binds org.apache.logging.log4j.core file:.../log4j-core-2.11.1.jar automatic org.slf4j binds org.apache.logging.log4j.slf4j file:.../log4j-slf4j18-impl-2.11.1.jar org.apache.logging.log4j.slf4j requires org.slf4j file:.../slf4j-api-1.8.0-beta2.jar org.apache.logging.log4j.slf4j requires org.apache.logging.log4j.core file:.../log4j-core-2.11.1.jar automatic org.apache.logging.log4j.slf4j requires org.apache.logging.log4j file:.../log4j-api-2.11.1.jar org.apache.logging.log4j binds org.apache.logging.log4j.core file:.../log4j-core-2.11.1.jar automatic 的服务无法从org.apache.logging.log4j.slf4j加载类(org.apache.logging.log4j.Logger)。在变量2中,来自org.apache.logging.log4j.core的服务加载了org.apache.logging.log4j.slf4j的所有类,一切正常。我们在变量2的输出中看到一行

org.apache.logging.log4j.core

,并且变量1中没有这样的行。这是问题所在吗?但是,如果两个模块是自动的,则不能自动解决吗?

1 个答案:

答案 0 :(得分:3)

SLF4J 1.8需要将org.slf4j.spi.SLF4JServiceProvider实现为公开服务。发现在log4j-slf4j18-impl jar中。但是,Log4j SLF4J桥需要Log4J API(模块org.apache.logging.log4j)。即使这是一个显式的Java模块,因为它仅从自动模块中引用,所以它没有被加载,从而导致ClassNotFoundException。

一个简单的解决方案是在启动应用程序时在命令行上包括--addmodules = org.apache.logging.log4j。