Здесь вы можете найти следующие сведения об автоматических модулях:
Модульная система также сканирует 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 / 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
и экспортировать сервис в формате JPMS через provides ... with..
. И проблема была решена - я не получаю NoClassDefFoundError
. Это ссылка на проблему.
Итак, мои вопросы:
- Службы поддержки JPMS в META-INF / службы автоматических модулей?
- если да, то как объяснить такое поведение?
EDIT
Всего 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
VARIANT 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
VARIANT 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 такой строки нет. Проблема в этом? Но если два модуля являются автоматическими, они не могут быть разрешены автоматически?