1. 前言

  从写代码开始,就陆陆续续接触到了许多日志框架,较常用的属于LOG4J,LogBack等。每次自己写项目时,就copy前人的代码或网上的demo。配置log4j.properties或者logback.properties就能搞定。这种思想一直持续到最近,前几天写了一个小demo,放在liunx上跑的时候竟然报stackOverFlow异常,仔细看异常信息,log4j-over-slf4j与slf4j-log4j12共存导致stack overflow异常,这一刻终于来了,我不得不去正式日志框架了。

2. 解决方案

  先贴一下我的解决方案。既然报冲突了,不管三七二十一,先删除一个jar包就OK!第一种解决方案直接在项目的WEB-INF\lib下删除slf4j-log4j12.jar包。

cd /WEB-INF/lib
rm -rf slf4j-log4j12-1.7..jar

  这种方案只是临时方案,再次打包部署时还会出现此问题。第二种方案是在pom.xml找到引用此JAR包的地方,我是因为引入了zookeeper,自带了此JAR包。使用<exclusion>标签排除此JAR包。或者使用<packagingExcludes>标签在打包时排除此JAR包。个人推荐使用<packagingExcludes>,因为我的<exclusion>标签不管用,此处不做详解,直接贴代码!

<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
<exclusions>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<packagingExcludes>WEB-INF/lib/slf4j-log4j12-1.7.25.jar</packagingExcludes>
</configuration>
</plugin>

3. 基本日志框架之间关系

  类比java的面向接口编程思想,JAVA日志框架分为接口层,实现层,还多了个桥接层,桥接层联系接口层和实现层。

  

  接口层:SELF4J,COMMONS-LOGGING

  实现层:LOG4J,LOGBACK,JDK-LOOGING,LOG4J2

  以上为通用的日志框架实现(即实现)和门面(即接口)。日志门面的出现很大程度缓解了日志系统的混乱,很多库的作者不在使用具体的日志框架实现了,而是去使用接口层,即面向接口编程。此处,贴一段话,方面更能理解。

  应用程序直接使用这些具体日志框架的API来满足日志输出需求当然是可以的,但是由于各个日志框架之间的API通常是不兼容的,这样做就使得应用程序丧失了更换日志框架的灵活性。比直接使用具体日志框架API更合理的选择是使用日志门面接口。日志门面接口提供了一套独立于具体日志框架实现的API,应用程序通过使用这些独立的API就能够实现与具体日志框架的解耦,这跟JDBC是类似的。最早的日志门面接口是commons-logging,但目前最受欢迎的是slf4j。日志门面接口本身通常并没有实际的日志输出能力,它底层还是需要去调用具体的日志框架API的,也就是实际上它需要跟具体的日志框架结合使用。由于具体日志框架比较多,而且互相也大都不兼容,日志门面接口要想实现与任意日志框架结合可能需要对应的桥接器,就好像JDBC与各种不同的数据库之间的结合需要对应的JDBC驱动一样。

4. StackOverFlow异常分析

  

  上图来自SLF4J官网。如图,上层都是使用SLF4JAPI对外暴露接口。SLF4JAPI使用的是slf4j-api.jar包。接着下层各个日志框架的实现就不一样了,最左边的是slf4j的一个空实现。第二列和第五列是logback和slf4j的一个简单实现,这2个框架没有使用所谓的桥接器,直接继承slf4j,实现slf4j的接口。log4j和jul的实现是要依靠桥接器,如上,slf4j-log412.jar和slf4j-jdk14.jar就是桥接器,分别连接slf4j,log4j和slf4j,jul。下面的log4j.jar和JVM runtime便是具体实现。

  其他日志系统转掉回slf4j,如果只存在slf-4j转到日志系统实现类,便不会存在StackOverFlow的异常。如果我们使用log4j日志系统,但又想使用别的日志系统,此时就要使用从日志系统到slf4j的桥接类 log4j-over-slf4j,这个库定义了与log4j一致的接口(包名、类名、方法签名均一致),但是接口的实现却是对slf4j日志接口的包装,即间接调用了slf4j日志接口,实现了对日志的转发。

  既然存在这么多桥接器,万一我的系统中存在slf4j -> log4j 和 log4j -> slf4j的桥接器。。。。就会出现互相委托,无限循环,堆栈溢出的状况。所有就会有出现异常。slf4j关于桥接器的详细介绍参考slf4j官方网站:https://www.slf4j.org/legacy.html

  比如,我现在想使用slf4j的实现类logback日志框架

  1. 引入slf4j & logback日志包和slf4j -> logback桥接器;

  2. 排除common-logging、log4j、log4j2日志包;

  3. 引入jdk-logging -> slf4j、common-logging -> slf4j、log4j -> slf4j、log4j2 -> slf4j桥接器;

  4. 排除slf4j -> jdk-logging、slf4j -> common-logging、slf4j -> log4j、slf4j -> log4j2桥接器。

 

  

Java日志框架总结的更多相关文章

  1. Java程序员最常用的8个Java日志框架

    转自:http://www.codeceo.com/article/8-java-log-framework.html 作为一名Java程序员,我们开发了很多Java应用程序,包括桌面应用.WEB应用 ...

  2. 转:Java程序员最常用的8个Java日志框架

    作为一名Java程序员,我们开发了很多Java应用程序,包括桌面应用.WEB应用以及移动应用.然而日志系统是一个成熟Java应用所必不可少的,在开发和调试阶段,日志可以帮助我们更好更快地定位bug:在 ...

  3. Java 日志框架终极教程

    概述 对于现代的 Java 应用程序来说,只要被部署到真实的生产环境,其日志的重要性就是不言而喻的,很难想象没有任何日志记录功能的应用程序被运行于生产环境中.日志 API 所能提供的功能是多种多样的, ...

  4. Java日志框架那些事儿

    文章首发于[博客园-陈树义],点击跳转到原文Java日志框架那些事儿. 在项目开发过程中,我们可以通过 debug 查找问题.而在线上环境我们查找问题只能通过打印日志的方式查找问题.因此对于一个项目而 ...

  5. Java基础学习总结(40)——Java程序员最常用的8个Java日志框架

    作为一名Java程序员,我们开发了很多Java应用程序,包括桌面应用.WEB应用以及移动应用.然而日志系统是一个成熟Java应用所必不可少的,在开发和调试阶段,日志可以帮助我们更好更快地定位bug:在 ...

  6. Java-最常用的Java日志框架整理

    Java-最常用的Java日志框架整理 前言 Java程序员,我们开发了很多Java应用程序,包括桌面应用.WEB应用以及移动应用.然而日志系统是一个成熟Java应用所必不可少的,在开发和调试阶段,日 ...

  7. java日志框架系列(4):logback框架xml配置文件语法

    1.xml配置文件语法 由于logback配置文件语法特别灵活,因此无法用DTD或schema进行定义. 1.配置文件基本结构 配置文件基本结构:以<configuration>标签开头, ...

  8. Java日志框架:SLF4J,Common-Logging,Log4J,Logback说明

    Log4j  Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.GUI组件.甚至是套接口服务 器.NT的事件记录器.UNIX Syslog守护进程等 ...

  9. java日志框架slf4j与log4j

    日志记录自然是非常重要的,但恐怕能记住slf4j与log4j等日志框架配置的人就很少了,这个东西不难,只是配置好后很少会去动它,开发新项目一般也是从其他项目拷贝,或者参照文档 废话不多说,先说log4 ...

随机推荐

  1. Apache NiFi 核心概念和关键特性

    本文来源于官方文档翻译 NiFi 的核心概念 NiFi 最早是美国国家安全局内部使用的工具,用来投递海量的传感器数据.后来由 apache 基金会开源.天生就具备强大的基因.NiFi基本设计理念与 F ...

  2. 一个项目的SpringCloud微服务改造过程

    SSO是公司一个已经存在了若干年的项目,后端采用SpringMVC.MyBatis,数据库使用MySQL,前端展示使用Freemark.今年,我们对该项目进行了一次革命性的改进,改造成SpringCl ...

  3. spring aop 解决模糊查询参数 % - /等特殊符号问题

    import com.hsq.common.utils.StringUtil;import org.aspectj.lang.ProceedingJoinPoint;import org.aspect ...

  4. python3学习-Queue模块

    python标准库中带有一个Queue模块,顾名思义,队列.该模块也衍生出一些基本队列不具有的功能. 我们先看一下队列的方法: put 存数据 get 取数据 empty 判断队列是否为空 qsize ...

  5. 高性能MySQL之事物

    一.概念 事务到底是什么东西呢?想必大家学习的时候也是对事务的概念很模糊的.接下来通过一个经典例子讲解事务. 银行在两个账户之间转账,从A账户转入B账户1000元,系统先减少A账户的1000元,然后再 ...

  6. MBR和EFI启动过程

    MBR启动过程 BIOS-->MBR(主引导记录)-->DPT(硬盘分区表)-->DBR(分区引导扇区)-->BootMgr-->BCD-->Winload.exe ...

  7. Appium+python自动化(三十三)- 环境(超详解)

    简介 在前边所有涉及启动app的时候有这样一行代码driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps),很多小 ...

  8. Joda Time使用小结

    一.Joda Time基础操作 1. 构造指定时间 // 明确给出年月日时分秒,同时还可以指定毫秒 DateTime dateTime = new DateTime(2017,9,14,20,30,0 ...

  9. Mac 打造开发工作环境

    近日公司配的dell笔记本越来越难担重任(主要是CPU太差,本人是Java开发,IDE一编译CPU就100%),于是狠下心入手了一台常规顶配Macbook Pro,现记录新本本的调教过程. Homeb ...

  10. 记录一次Jquery中 this 关键字使用出现的问题

    今天在用Jquery改造之前的JS代码过程中,遇到了一个让我懵逼了三小时的问题. 问题的关键在 this 的使用.在这里与大家分享一下.并且分享一下我做表单提交的检查代码 错误代码如下: $(&quo ...