Java17 Maven项目命令行启动报org.apache.logging.log4j.Logger类缺失求助
问题场景
- Java 17 Maven模块化项目,采用log4j2实现的slf4j日志框架
- Eclipse中启动运行正常,但命令行启动时抛出
NoClassDefFoundError - 已确认主类配置在模块JAR的MANIFEST中,所有依赖JAR存放于
target/lib目录,且log4j-api-3.0.0-alpha1.jar包含org.apache.logging.log4j.Logger类(验证命令如下):
for i in target/lib/*.jar; do jar -tvf "$i" | grep -Hsi org.apache.logging.log4j.Logger; done
- 错误的启动命令:
java -p target/lib -m eu.ngong.iqStm
- 报错栈:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/logging/log4j/Logger
at log4j.slf4j2.impl@3.0.0-alpha1/org.apache.logging.slf4j.SLF4JServiceProvider.initialize(SLF4JServiceProvider.java:53)
at org.slf4j@2.0.9/org.slf4j.LoggerFactory.bind(LoggerFactory.java:195)
at org.slf4j@2.0.9/org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:182)
at org.slf4j@2.0.9/org.slf4j.LoggerFactory.getProvider(LoggerFactory.java:490)
at org.slf4j@2.0.9/org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:476)
at org.slf4j@2.0.9/org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:425)
at org.slf4j@2.0.9/org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:451)
at eu.ngong.iqStm@0.0.2/eu.ngong.iqStm.App.(App.java:30)
Caused by: java.lang.ClassNotFoundException: org.apache.logging.log4j.Logger
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
... 8 more
原因分析
- 模块化规则限制:命令行启动时使用
-p(模块路径)参数,Java只会识别包含module-info.class的模块化JAR。若log4j-api-3.0.0-alpha1.jar是自动模块(无显式module-info),且主模块未声明依赖,会导致类加载失败。 - 模块依赖未声明:log4j-slf4j2-impl模块依赖log4j-api模块,若主模块
eu.ngong.iqStm的module-info.java未声明对这两个模块的依赖,模块化系统不会自动解析依赖关系。 - Eclipse与命令行的差异:Eclipse启动时会自动兼容模块化与非模块化JAR的混合场景,而命令行启动严格遵循Java模块化规范,未声明的依赖不会被自动加载。
解决方法与正确启动命令
方法1:修复模块依赖声明
在主模块的module-info.java中添加必要的模块依赖:
module eu.ngong.iqStm { requires org.slf4j; requires org.apache.logging.log4j; requires org.apache.logging.log4j.slf4j2.impl; // 其他业务所需的模块依赖 exports eu.ngong.iqStm; // 按需导出包 }
重新编译打包后,使用原命令启动:
java -p target/lib -m eu.ngong.iqStm
方法2:切换到类路径启动(兼容非模块化依赖)
若不想调整模块声明,可采用类路径模式启动,该模式对非模块化JAR兼容性更好:
# Linux/macOS java -cp "target/lib/*:target/eu.ngong.iqStm-0.0.2.jar" eu.ngong.iqStm.App # Windows java -cp "target/lib/*;target/eu.ngong.iqStm-0.0.2.jar" eu.ngong.iqStm.App
注意替换实际的模块JAR文件名
方法3:确认log4j-api的模块化状态
检查log4j-api-3.0.0-alpha1.jar是否包含module-info.class:
- 若为模块化JAR,模块名通常为
org.apache.logging.log4j,需确保主模块已声明requires org.apache.logging.log4j; - 若为自动模块,Java会以JAR文件名(去掉版本)作为模块名,同样需要主模块声明对应依赖
内容的提问来源于stack exchange,提问作者ngong

