sl4j的多种log4j实现导致日志不能打印

本文介绍了一个因日志jar冲突导致项目日志无法打印的问题及解决方法。通过分析pom文件和日志输出,找到了冲突源头并成功排除。同时讨论了隐式依赖带来的问题。

前言

目前在做项目过程中,发现部分项目的日志无法打印,一直不知道原因。分析发现是日志jar冲突,由于日志jar冲突是隐式引用,很难排查,加上我们经常不注意日志本身的报错。

1. 冲突jar

模拟jar冲突的project,pom如下

<dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.6.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.10.0</version>
        </dependency>


        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.26</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.10.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.10.0</version>
        </dependency>

    </dependencies>

随意写一个log4j2.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="info">
    <Appenders>
        <Console name="console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{DATE} %c{1}:%L - %m%n" />
        </Console>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="console" />
        </Root>
    </Loggers>
</Configuration>

写一个测试方法,这里说一下sl4j是日志接口,没有实现,可以集成log4j2与logback等,推荐使用打日志。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Slf4jDemo {
    private static final Logger logger = LoggerFactory.getLogger(Slf4jDemo.class);

    public static void main(String[] args) {
        logger.info("----------------------------");
    }
}

运行结果如下:

/software/jdk1.8.0_191/bin/java -javaagent:/software/ideaIde/lib/idea_rt.jar=36051:/software/ideaIde/bin -Dfile.encoding=UTF-8 -classpath /software/jdk1.8.0_191/jre/lib/charsets.jar:/software/jdk1.8.0_191/jre/lib/deploy.jar:/software/jdk1.8.0_191/jre/lib/ext/cldrdata.jar:/software/jdk1.8.0_191/jre/lib/ext/dnsns.jar:/software/jdk1.8.0_191/jre/lib/ext/jaccess.jar:/software/jdk1.8.0_191/jre/lib/ext/jfxrt.jar:/software/jdk1.8.0_191/jre/lib/ext/localedata.jar:/software/jdk1.8.0_191/jre/lib/ext/nashorn.jar:/software/jdk1.8.0_191/jre/lib/ext/sunec.jar:/software/jdk1.8.0_191/jre/lib/ext/sunjce_provider.jar:/software/jdk1.8.0_191/jre/lib/ext/sunpkcs11.jar:/software/jdk1.8.0_191/jre/lib/ext/zipfs.jar:/software/jdk1.8.0_191/jre/lib/javaws.jar:/software/jdk1.8.0_191/jre/lib/jce.jar:/software/jdk1.8.0_191/jre/lib/jfr.jar:/software/jdk1.8.0_191/jre/lib/jfxswt.jar:/software/jdk1.8.0_191/jre/lib/jsse.jar:/software/jdk1.8.0_191/jre/lib/management-agent.jar:/software/jdk1.8.0_191/jre/lib/plugin.jar:/software/jdk1.8.0_191/jre/lib/resources.jar:/software/jdk1.8.0_191/jre/lib/rt.jar:/home/huahua/IdeaProjects/demo/target/classes:/home/huahua/.m2/repository/org/slf4j/slf4j-log4j12/1.6.1/slf4j-log4j12-1.6.1.jar:/home/huahua/.m2/repository/log4j/log4j/1.2.16/log4j-1.2.16.jar:/home/huahua/.m2/repository/org/apache/logging/log4j/log4j-slf4j-impl/2.10.0/log4j-slf4j-impl-2.10.0.jar:/home/huahua/.m2/repository/org/slf4j/slf4j-api/1.7.26/slf4j-api-1.7.26.jar:/home/huahua/.m2/repository/org/apache/logging/log4j/log4j-api/2.10.0/log4j-api-2.10.0.jar:/home/huahua/.m2/repository/org/apache/logging/log4j/log4j-core/2.10.0/log4j-core-2.10.0.jar com.feng.demo.Slf4jDemo
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/home/huahua/.m2/repository/org/slf4j/slf4j-log4j12/1.6.1/slf4j-log4j12-1.6.1.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/huahua/.m2/repository/org/apache/logging/log4j/log4j-slf4j-impl/2.10.0/log4j-slf4j-impl-2.10.0.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]
log4j:WARN No appenders could be found for logger (com.feng.demo.Slf4jDemo).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

Process finished with exit code 0

由于经常忽略wran日志,项目启动后仅有少量的业务日志(估计有些日志不是log4j实现的),所以很难排查问题。

其实上面的日志已经说明了冲突的地方

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/home/huahua/.m2/repository/org/slf4j/slf4j-log4j12/1.6.1/slf4j-log4j12-1.6.1.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/huahua/.m2/repository/org/apache/logging/log4j/log4j-slf4j-impl/2.10.0/log4j-slf4j-impl-2.10.0.jar!/org/slf4j/impl/StaticLoggerBinder.class]

org/slf4j/impl/StaticLoggerBinder.class在2个jar

slf4j-log4j12-1.6.1.jar

log4j-slf4j-impl-2.10.0.jar

都有实现,由于使用的log4j2,slf4j-log4j12-1.6.1.jar是log4j的1.x版本用的,只有删除依赖就可以了。

删除后日志正常

30 三月 2019 10:23:55,282 Slf4jDemo:10 - ----------------------------

2. 隐式依赖冲突

我们知道使用log4j2不会引用log4j的1.x的版本,那么上面的依赖怎么来的呢,这里就是隐式依赖造成的

笔者是使用zookeeper的jar没注意引入的,比如zookeeper的3.4.13的jar

<!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.4.13</version>
    <type>pom</type>
</dependency>

在mvnrepository.com中明确说明依赖log4j的1.x的jar

intellij idea也可以看见 

需要exclude掉log4j的1.x的jar

 

总结

jar冲突其实也还好解决,日志都会有提示的,只是平时没注意 

<think>我们被要求用中文回答问题,并在最后提出3-5个相关问题,以“§§相关问题§§”开头,且禁止换行分散。 问题:sl4jlog4j有什么区别? 回答思路: 1. 解释SLF4JLog4j的基本概念和定位 2. 说明它们之间的关系(SLF4J是门面,Log4j是具体实现) 3. 比较两者的主要区别(接口vs实现、绑定机制、使用方式等) 4. 给出使用建议或示例 注意:用户要求最后必须输出“§§相关问题§§”并列出3-5个相关问题。 </think>SLF4J(Simple Logging Facade for Java)和Log4j是Java领域两个主流的日志工具,它们的主要区别如下: ### 核心区别对比表 | **特性** | **SLF4J** | **Log4j (1.x/2.x)** | |----------------|--------------------------------------|-------------------------------------| | **本质** | 日志门面(抽象层) | 日志实现(具体框架) | | **耦合性** | 解耦应用与具体日志实现 | 直接绑定具体实现 | | **日志输出** | 需绑定实现层(如Log4j, Logback等) | 可直接输出日志 | | **部署依赖** | slf4j-api.jar + 绑定器(可选) | log4j-core.jar(必需) | | **占位符** | `{}` 惰性求值(性能更优) | `{}`(仅Log4j2支持)或拼接字符串 | | **配置方式** | 无独立配置,依赖底层实现 | 独立配置文件(log4j2.xml/properties)| ### 详细解析 1. **架构角色不同** - **SLF4J**:日志门面(Facade),提供统一API,不处理实际日志输出(类似JDBC驱动接口) - **Log4j**:具体实现框架(实际执行日志记录),分经典版(1.x)和重构版(2.x) 2. **使用方式对比** ```java // SLF4J(需绑定Log4j实现) import org.slf4j.Logger; import org.slf4j.LoggerFactory; Logger logger = LoggerFactory.getLogger(MyClass.class); logger.debug("用户 {} 登录失败,尝试次数: {}", username, attempts); // 惰性求值 // Log4j 2.x 原生API import org.apache.logging.log4j.LogManager; Logger logger = LogManager.getLogger(); logger.debug("用户 {} 登录失败", username); // 2.x支持占位符 ``` 3. **典型组合方案** - **SLF4J + Log4j2**:主流方案(通过`slf4j-to-log4j2`适配器) - **SLF4J + Logback**:性能最优组合(无需适配器) - **纯Log4j2**:直接使用原生API(无需门面) 4. **性能关键点** - SLF4J的`{}`占位符在**DEBUG级别禁用时不会执行字符串拼接**(避免性能损耗) - Log4j 2.x 异步日志性能优于Log4j 1.x ### 何时使用 - **选SLF4J**:需要灵活切换日志实现(如从Log4j切到Logback) - **选Log4j**:直接控制日志细节(如定制化Appender)或遗留系统维护
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值