Поддерживает ли 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
, Это ссылка на проблему.
Итак, мои вопросы:
- JPMS поддерживает службы в META-INF / службы автоматических модулей?
- если да, то как объяснить такое поведение?
РЕДАКТИРОВАТЬ Всего 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 в командной строке при запуске приложения.