Поддерживает ли JPMS сервисы от META-INF/ сервисы для автоматических модулей?

Здесь вы можете найти следующую информацию об автоматических модулях:

Модульная система также сканирует META-INF/services и заставляет автоматический модуль предоставлять названные в ней сервисы. Предполагается, что автоматический модуль может использовать все сервисы.

Однако у меня следующая ситуация. Я хочу использовать log4j2 с slf4j в JPMS. Для того, чтобы сделать это log4j-slf4j-impl-2.11.1.jar должен предоставить услугу JPMS slf4j-api-1.8.0-beta2.jar, Разработчики log4j сделали log4j-slf4j-impl-2.11.1.jar как автоматический модуль и предоставляемый сервис через META-INF / услуги. Однако, это не работает, это дает следующее:

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 и экспорт услуг в формате JPMS через provides ... with.., И проблема была решена - я не понимаю NoClassDefFoundError, Это ссылка на проблему.

Итак, мои вопросы:

  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 Если я запускаю --show-module-resolution когда 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 когда 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

В VARIANT 1 сервис от org.apache.logging.log4j.slf4j не могу загрузить класс (org.apache.logging.log4j.Logger) от org.apache.logging.log4j.core, В VARIANT 2 сервис от org.apache.logging.log4j.slf4j загружает все классы из org.apache.logging.log4j.core и все в порядке. Мы видим в выходе VARIANT 2, что есть линия

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

и нет такой строки в VARIANT 1. Проблема в этом? Но если два модуля являются автоматическими, они не могут быть разрешены автоматически?

1 ответ

Решение

SLF4J 1.8 требует реализации org.slf4j.spi.SLF4JServiceProvider в качестве открытой службы. Обнаружено, что в банке log4j-slf4j18-impl. Однако для моста Log4j SLF4J требуется API Log4J (модуль org.apache.logging.log4j). Несмотря на то, что это явный модуль Java, поскольку на него ссылаются только из автоматического модуля, он не загружается, что приводит к исключению ClassNotFoundException.

Простым решением этого является включение --addmodules=org.apache.logging.log4j в командной строке при запуске приложения.

Другие вопросы по тегам