代码之家  ›  专栏  ›  技术社区  ›  Pavel_K

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

  •  3
  • Pavel_K  · 技术社区  · 7 年前

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

    模块系统还扫描META-INF/services并使其自动运行 假定允许使用所有服务。

    不过,我有以下情况。我想在JPMS中使用log4j2和slf4j。为了做到这一点 log4j-slf4j-impl-2.11.1.jar slf4j-api-1.8.0-beta2.jar . log4j的开发者 log4j-slf4j-impl-2.11.1.jar文件

    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.. . 问题解决了-我什么都没有 NoClassDefFoundError . 这是 link 对这个问题。

    所以我的问题是:

    1. 如果是,那么如何解释这种行为?

    共有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 我得到以下输出(我用 ...

    ...
    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
    

    变型2 如果我运行--show module resolution when log4j-slf4j18-impl-2.11.1.jar module-info 我得到以下输出:

    ...
    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
    

    在变体1中,服务来自 org.apache.logging.log4j.slf4j 无法加载类( org.apache.logging.log4j.Logger org.apache.logging.log4j.core . 在变体2中,服务来自 org.apache.logging.log4j.slf4j org.apache.logging.log4j.core

    org.apache.logging.log4j.slf4j requires org.apache.logging.log4j.core
    

    在变体1中没有这样的行。问题出在这里吗?但是如果两个模块是自动的,它们就不能自动解析吗?

    1 回复  |  直到 7 年前
        1
  •  3
  •   rgoers    7 年前

    SLF4J 1.8需要org.SLF4J.spi.SLF4JServiceProvider的实现作为公开服务。在log4j-slf4j18-impl jar中发现。但是,log4jslf4j桥需要log4japi(module org.apache.logging.Log4j)。尽管这是一个显式的Java模块,但由于它只从自动模块中引用,因此不会加载它,从而导致ClassNotFoundException。

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

    推荐文章