当前位置: 首页 > 知识库问答 >
问题:

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

贝财
2023-03-14

在这里你可以找到以下关于自动模块的内容:

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

但是,我有以下情况。我想在JPMS中与slf4j一起使用log4j2。为此,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

我决定将module-info添加到log4j-SLF4j-impl-2.11.1.jar中,并通过provide..以JPMS方式导出服务。问题解决了--我没有得到任何NoClassDefoundErr。这是问题的链接。

所以我的问题是:

  1. JPMS是否支持自动模块的元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
...
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
...
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.core加载类(org.apache.logging.log4j.logger)。在变体2中,org.apache.logging.log4j.slf4j中的服务加载org.apache.logging.log4j.core中的所有类,一切正常。我们在变式2的输出中看到有一条线

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

而备选案文1中没有这一行。问题就在这里吗?但是如果两个模块是自动的,它们就不能自动解析吗?

共有1个答案

邵弘伟
2023-03-14

SLF4J1.8要求将org.SLF4J.spi.slf4jServiceProvider实现为公开服务。发现log4j-slf4j18-impl JAR。但是,Log4j SLF4J桥需要Log4j API(模块org.apache.logging.Log4j)。尽管这是一个显式的Java模块,但由于它只是从一个自动模块中引用的,所以没有加载它,导致ClassNotFoundException。

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

 类似资料:
  • 问题内容: 现在我不明白如何访问另一个模块上定义的服务状态? 我不应该对吗?但是我不知何故…或者这是正确的行为吗? 问题答案: 甲模块在配置和运行块的集合,其获得在引导过程中施加到该应用程序。模块可以列出其他模块作为它们的依存关系。根据模块上意味着 需要 将之前加载模块的需求 ,需要 加载的模块。 注入模块时,服务会在配置阶段进行注册,并且可以访问它们,因此总而言之,这是Angular中正确行为和

  • 问题内容: 我想像本例一样启用蓝牙。 但是,我的课程不是Activity,而是Service,因此我不能调用startActivityForResult。我怎么解决这个问题?。我知道还回答了其他问题,例如 使用非活动中的startActivityForResult 但这不能解决我的问题,因为我的应用程序由服务组成,而没有别的什么。 问题答案: 不幸的是你不能那样做。 我发现(破解)的唯一解决方案是

  • 问题内容: 我正在尝试在收到C2DM消息时显示一个简单的通知。服务提供给UI,但仍在主线程上运行。我见过有人声称您可以通过服务创建和显示通知。 } 我不知道为什么会抛出该异常。 问题答案: 首先,引发异常是因为创建的通知没有引用该对象的视图对象(contentView属性设置为null)。您必须在显示通知之前调用setLatestEventInfo。 其次,不赞成使用您使用的构造函数。请使用Not

  • 下面尝试过,但是直到并且除非我使Acyah geShipmentIn绑定节点为空(删除释放ID="9.2"xmlns="http://schema.infor.com/InforOAGIS/2"xmlns: xs="http://www.w3.org/2001/XMLSchema")选择查询不获取值。

  • 我们最近将一些数据移植到MongoDB,现在正在考虑运行日常备份,最好是从cron作业,并将其中一个备份恢复到辅助mongo数据库。 我们的系统设置如下: 服务器1:开发mongo数据库 服务器2:两个mongo数据库,一个用于暂存数据,一个用于生产 服务器3:是我们运行所有cron作业/批处理脚本的地方 (我尝试了将用户名和密码连接到主机,但没有将用户名和密码连接到主机) 我收到以下信息: Mo

  • 我有一个 Rest Controller 类,其中我正在自动布线服务层。现在我想模拟测试类中的服务层,但在运行我的测试类 控制器代码 测试类 我是JUnit5和Mockito的新手。有人能告诉我哪里错了吗?